{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# \u7b2c\u516b\u7ae0\uff1a\u7c7b\u4e0e\u5bf9\u8c61\n \u672c\u7ae0\u4e3b\u8981\u5173\u6ce8\u70b9\u7684\u662f\u548c\u7c7b\u5b9a\u4e49\u6709\u5173\u7684\u5e38\u89c1\u7f16\u7a0b\u6a21\u578b\u3002\u5305\u62ec\u8ba9\u5bf9\u8c61\u652f\u6301\u5e38\u89c1\u7684Python\u7279\u6027\u3001\u7279\u6b8a\u65b9\u6cd5\u7684\u4f7f\u7528\u3001\n\u7c7b\u5c01\u88c5\u6280\u672f\u3001\u7ee7\u627f\u3001\u5185\u5b58\u7ba1\u7406\u4ee5\u53ca\u6709\u7528\u7684\u8bbe\u8ba1\u6a21\u5f0f\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 8.1 \u6539\u53d8\u5bf9\u8c61\u7684\u5b57\u7b26\u4e32\u663e\u793a\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u60f3\u6539\u53d8\u5bf9\u8c61\u5b9e\u4f8b\u7684\u6253\u5370\u6216\u663e\u793a\u8f93\u51fa\uff0c\u8ba9\u5b83\u4eec\u66f4\u5177\u53ef\u8bfb\u6027\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8981\u6539\u53d8\u4e00\u4e2a\u5b9e\u4f8b\u7684\u5b57\u7b26\u4e32\u8868\u793a\uff0c\u53ef\u91cd\u65b0\u5b9a\u4e49\u5b83\u7684 __str__() \u548c __repr__() \u65b9\u6cd5\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class Pair:\n    def __init__(self, x, y):\n        self.x = x\n        self.y = y\n\n    def __repr__(self):\n        return 'Pair({0.x!r}, {0.y!r})'.format(self)\n\n    def __str__(self):\n        return '({0.x!s}, {0.y!s})'.format(self)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "__repr__() \u65b9\u6cd5\u8fd4\u56de\u4e00\u4e2a\u5b9e\u4f8b\u7684\u4ee3\u7801\u8868\u793a\u5f62\u5f0f\uff0c\u901a\u5e38\u7528\u6765\u91cd\u65b0\u6784\u9020\u8fd9\u4e2a\u5b9e\u4f8b\u3002\n\u5185\u7f6e\u7684 repr() \u51fd\u6570\u8fd4\u56de\u8fd9\u4e2a\u5b57\u7b26\u4e32\uff0c\u8ddf\u6211\u4eec\u4f7f\u7528\u4ea4\u4e92\u5f0f\u89e3\u91ca\u5668\u663e\u793a\u7684\u503c\u662f\u4e00\u6837\u7684\u3002\n__str__() \u65b9\u6cd5\u5c06\u5b9e\u4f8b\u8f6c\u6362\u4e3a\u4e00\u4e2a\u5b57\u7b26\u4e32\uff0c\u4f7f\u7528 str() \u6216 print() \u51fd\u6570\u4f1a\u8f93\u51fa\u8fd9\u4e2a\u5b57\u7b26\u4e32\u3002\u6bd4\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "p = Pair(3, 4)\np"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "print(p)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u6211\u4eec\u5728\u8fd9\u91cc\u8fd8\u6f14\u793a\u4e86\u5728\u683c\u5f0f\u5316\u7684\u65f6\u5019\u600e\u6837\u4f7f\u7528\u4e0d\u540c\u7684\u5b57\u7b26\u4e32\u8868\u73b0\u5f62\u5f0f\u3002\n\u7279\u522b\u6765\u8bb2\uff0c!r \u683c\u5f0f\u5316\u4ee3\u7801\u6307\u660e\u8f93\u51fa\u4f7f\u7528 __repr__() \u6765\u4ee3\u66ff\u9ed8\u8ba4\u7684 __str__() \u3002\n\u4f60\u53ef\u4ee5\u7528\u524d\u9762\u7684\u7c7b\u6765\u8bd5\u7740\u6d4b\u8bd5\u4e0b\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "p = Pair(3, 4)\nprint('p is {0!r}'.format(p))"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "print('p is {0}'.format(p))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u81ea\u5b9a\u4e49 __repr__() \u548c __str__() \u901a\u5e38\u662f\u5f88\u597d\u7684\u4e60\u60ef\uff0c\u56e0\u4e3a\u5b83\u80fd\u7b80\u5316\u8c03\u8bd5\u548c\u5b9e\u4f8b\u8f93\u51fa\u3002\n\u4f8b\u5982\uff0c\u5982\u679c\u4ec5\u4ec5\u53ea\u662f\u6253\u5370\u8f93\u51fa\u6216\u65e5\u5fd7\u8f93\u51fa\u67d0\u4e2a\u5b9e\u4f8b\uff0c\u90a3\u4e48\u7a0b\u5e8f\u5458\u4f1a\u770b\u5230\u5b9e\u4f8b\u66f4\u52a0\u8be6\u7ec6\u4e0e\u6709\u7528\u7684\u4fe1\u606f\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "__repr__() \u751f\u6210\u7684\u6587\u672c\u5b57\u7b26\u4e32\u6807\u51c6\u505a\u6cd5\u662f\u9700\u8981\u8ba9 eval(repr(x)) == x \u4e3a\u771f\u3002\n\u5982\u679c\u5b9e\u5728\u4e0d\u80fd\u8fd9\u6837\u5b50\u505a\uff0c\u5e94\u8be5\u521b\u5efa\u4e00\u4e2a\u6709\u7528\u7684\u6587\u672c\u8868\u793a\uff0c\u5e76\u4f7f\u7528 < \u548c > \u62ec\u8d77\u6765\u3002\u6bd4\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "f = open('file.dat')\nf"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c __str__() \u6ca1\u6709\u88ab\u5b9a\u4e49\uff0c\u90a3\u4e48\u5c31\u4f1a\u4f7f\u7528 __repr__() \u6765\u4ee3\u66ff\u8f93\u51fa\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e0a\u9762\u7684 format() \u65b9\u6cd5\u7684\u4f7f\u7528\u770b\u4e0a\u53bb\u5f88\u6709\u8da3\uff0c\u683c\u5f0f\u5316\u4ee3\u7801 {0.x} \u5bf9\u5e94\u7684\u662f\u7b2c1\u4e2a\u53c2\u6570\u7684x\u5c5e\u6027\u3002\n\u56e0\u6b64\uff0c\u5728\u4e0b\u9762\u7684\u51fd\u6570\u4e2d\uff0c0\u5b9e\u9645\u4e0a\u6307\u7684\u5c31\u662f self \u672c\u8eab\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "def __repr__(self):\n    return 'Pair({0.x!r}, {0.y!r})'.format(self)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f5c\u4e3a\u8fd9\u79cd\u5b9e\u73b0\u7684\u4e00\u4e2a\u66ff\u4ee3\uff0c\u4f60\u4e5f\u53ef\u4ee5\u4f7f\u7528 % \u64cd\u4f5c\u7b26\uff0c\u5c31\u50cf\u4e0b\u9762\u8fd9\u6837\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "def __repr__(self):\n    return 'Pair(%r, %r)' % (self.x, self.y)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 8.2 \u81ea\u5b9a\u4e49\u5b57\u7b26\u4e32\u7684\u683c\u5f0f\u5316\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u60f3\u901a\u8fc7 format() \u51fd\u6570\u548c\u5b57\u7b26\u4e32\u65b9\u6cd5\u4f7f\u5f97\u4e00\u4e2a\u5bf9\u8c61\u80fd\u652f\u6301\u81ea\u5b9a\u4e49\u7684\u683c\u5f0f\u5316\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e3a\u4e86\u81ea\u5b9a\u4e49\u5b57\u7b26\u4e32\u7684\u683c\u5f0f\u5316\uff0c\u6211\u4eec\u9700\u8981\u5728\u7c7b\u4e0a\u9762\u5b9a\u4e49 __format__() \u65b9\u6cd5\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "_formats = {\n    'ymd' : '{d.year}-{d.month}-{d.day}',\n    'mdy' : '{d.month}/{d.day}/{d.year}',\n    'dmy' : '{d.day}/{d.month}/{d.year}'\n    }\n\nclass Date:\n    def __init__(self, year, month, day):\n        self.year = year\n        self.month = month\n        self.day = day\n\n    def __format__(self, code):\n        if code == '':\n            code = 'ymd'\n        fmt = _formats[code]\n        return fmt.format(d=self)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u73b0\u5728 Date \u7c7b\u7684\u5b9e\u4f8b\u53ef\u4ee5\u652f\u6301\u683c\u5f0f\u5316\u64cd\u4f5c\u4e86\uff0c\u5982\u540c\u4e0b\u9762\u8fd9\u6837\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "d = Date(2012, 12, 21)\nformat(d)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "format(d, 'mdy')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "'The date is {:ymd}'.format(d)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "'The date is {:mdy}'.format(d)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "__format__() \u65b9\u6cd5\u7ed9Python\u7684\u5b57\u7b26\u4e32\u683c\u5f0f\u5316\u529f\u80fd\u63d0\u4f9b\u4e86\u4e00\u4e2a\u94a9\u5b50\u3002\n\u8fd9\u91cc\u9700\u8981\u7740\u91cd\u5f3a\u8c03\u7684\u662f\u683c\u5f0f\u5316\u4ee3\u7801\u7684\u89e3\u6790\u5de5\u4f5c\u5b8c\u5168\u7531\u7c7b\u81ea\u5df1\u51b3\u5b9a\u3002\u56e0\u6b64\uff0c\u683c\u5f0f\u5316\u4ee3\u7801\u53ef\u4ee5\u662f\u4efb\u4f55\u503c\u3002\n\u4f8b\u5982\uff0c\u53c2\u8003\u4e0b\u9762\u6765\u81ea datetime \u6a21\u5757\u4e2d\u7684\u4ee3\u7801\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "from datetime import date\nd = date(2012, 12, 21)\nformat(d)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "format(d,'%A, %B %d, %Y')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "'The end is {:%d %b %Y}. Goodbye'.format(d)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5bf9\u4e8e\u5185\u7f6e\u7c7b\u578b\u7684\u683c\u5f0f\u5316\u6709\u4e00\u4e9b\u6807\u51c6\u7684\u7ea6\u5b9a\u3002\n\u53ef\u4ee5\u53c2\u8003 string\u6a21\u5757\u6587\u6863 \u8bf4\u660e\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 8.3 \u8ba9\u5bf9\u8c61\u652f\u6301\u4e0a\u4e0b\u6587\u7ba1\u7406\u534f\u8bae\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u60f3\u8ba9\u4f60\u7684\u5bf9\u8c61\u652f\u6301\u4e0a\u4e0b\u6587\u7ba1\u7406\u534f\u8bae(with\u8bed\u53e5)\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e3a\u4e86\u8ba9\u4e00\u4e2a\u5bf9\u8c61\u517c\u5bb9 with \u8bed\u53e5\uff0c\u4f60\u9700\u8981\u5b9e\u73b0 __enter__() \u548c __exit__() \u65b9\u6cd5\u3002\n\u4f8b\u5982\uff0c\u8003\u8651\u5982\u4e0b\u7684\u4e00\u4e2a\u7c7b\uff0c\u5b83\u80fd\u4e3a\u6211\u4eec\u521b\u5efa\u4e00\u4e2a\u7f51\u7edc\u8fde\u63a5\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "from socket import socket, AF_INET, SOCK_STREAM\n\nclass LazyConnection:\n    def __init__(self, address, family=AF_INET, type=SOCK_STREAM):\n        self.address = address\n        self.family = family\n        self.type = type\n        self.sock = None\n\n    def __enter__(self):\n        if self.sock is not None:\n            raise RuntimeError('Already connected')\n        self.sock = socket(self.family, self.type)\n        self.sock.connect(self.address)\n        return self.sock\n\n    def __exit__(self, exc_ty, exc_val, tb):\n        self.sock.close()\n        self.sock = None"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u4e2a\u7c7b\u7684\u5173\u952e\u7279\u70b9\u5728\u4e8e\u5b83\u8868\u793a\u4e86\u4e00\u4e2a\u7f51\u7edc\u8fde\u63a5\uff0c\u4f46\u662f\u521d\u59cb\u5316\u7684\u65f6\u5019\u5e76\u4e0d\u4f1a\u505a\u4efb\u4f55\u4e8b\u60c5(\u6bd4\u5982\u5b83\u5e76\u6ca1\u6709\u5efa\u7acb\u4e00\u4e2a\u8fde\u63a5)\u3002\n\u8fde\u63a5\u7684\u5efa\u7acb\u548c\u5173\u95ed\u662f\u4f7f\u7528 with \u8bed\u53e5\u81ea\u52a8\u5b8c\u6210\u7684\uff0c\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "from functools import partial\n\nconn = LazyConnection(('www.python.org', 80))\n# Connection closed\nwith conn as s:\n    # conn.__enter__() executes: connection open\n    s.send(b'GET /index.html HTTP/1.0\\r\\n')\n    s.send(b'Host: www.python.org\\r\\n')\n    s.send(b'\\r\\n')\n    resp = b''.join(iter(partial(s.recv, 8192), b''))\n    # conn.__exit__() executes: connection closed"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u7f16\u5199\u4e0a\u4e0b\u6587\u7ba1\u7406\u5668\u7684\u4e3b\u8981\u539f\u7406\u662f\u4f60\u7684\u4ee3\u7801\u4f1a\u653e\u5230 with \u8bed\u53e5\u5757\u4e2d\u6267\u884c\u3002\n\u5f53\u51fa\u73b0 with \u8bed\u53e5\u7684\u65f6\u5019\uff0c\u5bf9\u8c61\u7684 __enter__() \u65b9\u6cd5\u88ab\u89e6\u53d1\uff0c\n\u5b83\u8fd4\u56de\u7684\u503c(\u5982\u679c\u6709\u7684\u8bdd)\u4f1a\u88ab\u8d4b\u503c\u7ed9 as \u58f0\u660e\u7684\u53d8\u91cf\u3002\u7136\u540e\uff0cwith \u8bed\u53e5\u5757\u91cc\u9762\u7684\u4ee3\u7801\u5f00\u59cb\u6267\u884c\u3002\n\u6700\u540e\uff0c__exit__() \u65b9\u6cd5\u88ab\u89e6\u53d1\u8fdb\u884c\u6e05\u7406\u5de5\u4f5c\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e0d\u7ba1 with \u4ee3\u7801\u5757\u4e2d\u53d1\u751f\u4ec0\u4e48\uff0c\u4e0a\u9762\u7684\u63a7\u5236\u6d41\u90fd\u4f1a\u6267\u884c\u5b8c\uff0c\u5c31\u7b97\u4ee3\u7801\u5757\u4e2d\u53d1\u751f\u4e86\u5f02\u5e38\u4e5f\u662f\u4e00\u6837\u7684\u3002\n\u4e8b\u5b9e\u4e0a\uff0c__exit__() \u65b9\u6cd5\u7684\u4e09\u4e2a\u53c2\u6570\u5305\u542b\u4e86\u5f02\u5e38\u7c7b\u578b\u3001\u5f02\u5e38\u503c\u548c\u8ffd\u6eaf\u4fe1\u606f(\u5982\u679c\u6709\u7684\u8bdd)\u3002\n__exit__() \u65b9\u6cd5\u80fd\u81ea\u5df1\u51b3\u5b9a\u600e\u6837\u5229\u7528\u8fd9\u4e2a\u5f02\u5e38\u4fe1\u606f\uff0c\u6216\u8005\u5ffd\u7565\u5b83\u5e76\u8fd4\u56de\u4e00\u4e2aNone\u503c\u3002\n\u5982\u679c __exit__() \u8fd4\u56de True \uff0c\u90a3\u4e48\u5f02\u5e38\u4f1a\u88ab\u6e05\u7a7a\uff0c\u5c31\u597d\u50cf\u4ec0\u4e48\u90fd\u6ca1\u53d1\u751f\u4e00\u6837\uff0c\nwith \u8bed\u53e5\u540e\u9762\u7684\u7a0b\u5e8f\u7ee7\u7eed\u5728\u6b63\u5e38\u6267\u884c\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd8\u6709\u4e00\u4e2a\u7ec6\u8282\u95ee\u9898\u5c31\u662f LazyConnection \u7c7b\u662f\u5426\u5141\u8bb8\u591a\u4e2a with \u8bed\u53e5\u6765\u5d4c\u5957\u4f7f\u7528\u8fde\u63a5\u3002\n\u5f88\u663e\u7136\uff0c\u4e0a\u9762\u7684\u5b9a\u4e49\u4e2d\u4e00\u6b21\u53ea\u80fd\u5141\u8bb8\u4e00\u4e2asocket\u8fde\u63a5\uff0c\u5982\u679c\u6b63\u5728\u4f7f\u7528\u4e00\u4e2asocket\u7684\u65f6\u5019\u53c8\u91cd\u590d\u4f7f\u7528 with \u8bed\u53e5\uff0c\n\u5c31\u4f1a\u4ea7\u751f\u4e00\u4e2a\u5f02\u5e38\u4e86\u3002\u4e0d\u8fc7\u4f60\u53ef\u4ee5\u50cf\u4e0b\u9762\u8fd9\u6837\u4fee\u6539\u4e0b\u4e0a\u9762\u7684\u5b9e\u73b0\u6765\u89e3\u51b3\u8fd9\u4e2a\u95ee\u9898\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "from socket import socket, AF_INET, SOCK_STREAM\n\nclass LazyConnection:\n    def __init__(self, address, family=AF_INET, type=SOCK_STREAM):\n        self.address = address\n        self.family = family\n        self.type = type\n        self.connections = []\n\n    def __enter__(self):\n        sock = socket(self.family, self.type)\n        sock.connect(self.address)\n        self.connections.append(sock)\n        return sock\n\n    def __exit__(self, exc_ty, exc_val, tb):\n        self.connections.pop().close()\n\n# Example use\nfrom functools import partial\n\nconn = LazyConnection(('www.python.org', 80))\nwith conn as s1:\n    pass\n    with conn as s2:\n        pass\n        # s1 and s2 are independent sockets"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5728\u7b2c\u4e8c\u4e2a\u7248\u672c\u4e2d\uff0cLazyConnection \u7c7b\u53ef\u4ee5\u88ab\u770b\u505a\u662f\u67d0\u4e2a\u8fde\u63a5\u5de5\u5382\u3002\u5728\u5185\u90e8\uff0c\u4e00\u4e2a\u5217\u8868\u88ab\u7528\u6765\u6784\u9020\u4e00\u4e2a\u6808\u3002\n\u6bcf\u6b21 __enter__() \u65b9\u6cd5\u6267\u884c\u7684\u65f6\u5019\uff0c\u5b83\u590d\u5236\u521b\u5efa\u4e00\u4e2a\u65b0\u7684\u8fde\u63a5\u5e76\u5c06\u5176\u52a0\u5165\u5230\u6808\u91cc\u9762\u3002\n__exit__() \u65b9\u6cd5\u7b80\u5355\u7684\u4ece\u6808\u4e2d\u5f39\u51fa\u6700\u540e\u4e00\u4e2a\u8fde\u63a5\u5e76\u5173\u95ed\u5b83\u3002\n\u8fd9\u91cc\u7a0d\u5fae\u6709\u70b9\u96be\u7406\u89e3\uff0c\u4e0d\u8fc7\u5b83\u80fd\u5141\u8bb8\u5d4c\u5957\u4f7f\u7528 with \u8bed\u53e5\u521b\u5efa\u591a\u4e2a\u8fde\u63a5\uff0c\u5c31\u5982\u4e0a\u9762\u6f14\u793a\u7684\u90a3\u6837\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5728\u9700\u8981\u7ba1\u7406\u4e00\u4e9b\u8d44\u6e90\u6bd4\u5982\u6587\u4ef6\u3001\u7f51\u7edc\u8fde\u63a5\u548c\u9501\u7684\u7f16\u7a0b\u73af\u5883\u4e2d\uff0c\u4f7f\u7528\u4e0a\u4e0b\u6587\u7ba1\u7406\u5668\u662f\u5f88\u666e\u904d\u7684\u3002\n\u8fd9\u4e9b\u8d44\u6e90\u7684\u4e00\u4e2a\u4e3b\u8981\u7279\u5f81\u662f\u5b83\u4eec\u5fc5\u987b\u88ab\u624b\u52a8\u7684\u5173\u95ed\u6216\u91ca\u653e\u6765\u786e\u4fdd\u7a0b\u5e8f\u7684\u6b63\u786e\u8fd0\u884c\u3002\n\u4f8b\u5982\uff0c\u5982\u679c\u4f60\u8bf7\u6c42\u4e86\u4e00\u4e2a\u9501\uff0c\u90a3\u4e48\u4f60\u5fc5\u987b\u786e\u4fdd\u4e4b\u540e\u91ca\u653e\u4e86\u5b83\uff0c\u5426\u5219\u5c31\u53ef\u80fd\u4ea7\u751f\u6b7b\u9501\u3002\n\u901a\u8fc7\u5b9e\u73b0 __enter__() \u548c __exit__() \u65b9\u6cd5\u5e76\u4f7f\u7528 with \u8bed\u53e5\u53ef\u4ee5\u5f88\u5bb9\u6613\u7684\u907f\u514d\u8fd9\u4e9b\u95ee\u9898\uff0c\n\u56e0\u4e3a __exit__() \u65b9\u6cd5\u53ef\u4ee5\u8ba9\u4f60\u65e0\u9700\u62c5\u5fc3\u8fd9\u4e9b\u4e86\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5728 contextmanager \u6a21\u5757\u4e2d\u6709\u4e00\u4e2a\u6807\u51c6\u7684\u4e0a\u4e0b\u6587\u7ba1\u7406\u65b9\u6848\u6a21\u677f\uff0c\u53ef\u53c2\u80039.22\u5c0f\u8282\u3002\n\u540c\u65f6\u572812.6\u5c0f\u8282\u4e2d\u8fd8\u6709\u4e00\u4e2a\u5bf9\u672c\u8282\u793a\u4f8b\u7a0b\u5e8f\u7684\u7ebf\u7a0b\u5b89\u5168\u7684\u4fee\u6539\u7248\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 8.4 \u521b\u5efa\u5927\u91cf\u5bf9\u8c61\u65f6\u8282\u7701\u5185\u5b58\u65b9\u6cd5\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u7684\u7a0b\u5e8f\u8981\u521b\u5efa\u5927\u91cf(\u53ef\u80fd\u4e0a\u767e\u4e07)\u7684\u5bf9\u8c61\uff0c\u5bfc\u81f4\u5360\u7528\u5f88\u5927\u7684\u5185\u5b58\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5bf9\u4e8e\u4e3b\u8981\u662f\u7528\u6765\u5f53\u6210\u7b80\u5355\u7684\u6570\u636e\u7ed3\u6784\u7684\u7c7b\u800c\u8a00\uff0c\u4f60\u53ef\u4ee5\u901a\u8fc7\u7ed9\u7c7b\u6dfb\u52a0 __slots__ \u5c5e\u6027\u6765\u6781\u5927\u7684\u51cf\u5c11\u5b9e\u4f8b\u6240\u5360\u7684\u5185\u5b58\u3002\u6bd4\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class Date:\n    __slots__ = ['year', 'month', 'day']\n    def __init__(self, year, month, day):\n        self.year = year\n        self.month = month\n        self.day = day"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5f53\u4f60\u5b9a\u4e49 __slots__ \u540e\uff0cPython\u5c31\u4f1a\u4e3a\u5b9e\u4f8b\u4f7f\u7528\u4e00\u79cd\u66f4\u52a0\u7d27\u51d1\u7684\u5185\u90e8\u8868\u793a\u3002\n\u5b9e\u4f8b\u901a\u8fc7\u4e00\u4e2a\u5f88\u5c0f\u7684\u56fa\u5b9a\u5927\u5c0f\u7684\u6570\u7ec4\u6765\u6784\u5efa\uff0c\u800c\u4e0d\u662f\u4e3a\u6bcf\u4e2a\u5b9e\u4f8b\u5b9a\u4e49\u4e00\u4e2a\u5b57\u5178\uff0c\u8fd9\u8ddf\u5143\u7ec4\u6216\u5217\u8868\u5f88\u7c7b\u4f3c\u3002\n\u5728 __slots__ \u4e2d\u5217\u51fa\u7684\u5c5e\u6027\u540d\u5728\u5185\u90e8\u88ab\u6620\u5c04\u5230\u8fd9\u4e2a\u6570\u7ec4\u7684\u6307\u5b9a\u5c0f\u6807\u4e0a\u3002\n\u4f7f\u7528slots\u4e00\u4e2a\u4e0d\u597d\u7684\u5730\u65b9\u5c31\u662f\u6211\u4eec\u4e0d\u80fd\u518d\u7ed9\u5b9e\u4f8b\u6dfb\u52a0\u65b0\u7684\u5c5e\u6027\u4e86\uff0c\u53ea\u80fd\u4f7f\u7528\u5728 __slots__ \u4e2d\u5b9a\u4e49\u7684\u90a3\u4e9b\u5c5e\u6027\u540d\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f7f\u7528slots\u540e\u8282\u7701\u7684\u5185\u5b58\u4f1a\u8ddf\u5b58\u50a8\u5c5e\u6027\u7684\u6570\u91cf\u548c\u7c7b\u578b\u6709\u5173\u3002\n\u4e0d\u8fc7\uff0c\u4e00\u822c\u6765\u8bb2\uff0c\u4f7f\u7528\u5230\u7684\u5185\u5b58\u603b\u91cf\u548c\u5c06\u6570\u636e\u5b58\u50a8\u5728\u4e00\u4e2a\u5143\u7ec4\u4e2d\u5dee\u4e0d\u591a\u3002\n\u4e3a\u4e86\u7ed9\u4f60\u4e00\u4e2a\u76f4\u89c2\u8ba4\u8bc6\uff0c\u5047\u8bbe\u4f60\u4e0d\u4f7f\u7528slots\u76f4\u63a5\u5b58\u50a8\u4e00\u4e2aDate\u5b9e\u4f8b\uff0c\n\u572864\u4f4d\u7684Python\u4e0a\u9762\u8981\u5360\u7528428\u5b57\u8282\uff0c\u800c\u5982\u679c\u4f7f\u7528\u4e86slots\uff0c\u5185\u5b58\u5360\u7528\u4e0b\u964d\u5230156\u5b57\u8282\u3002\n\u5982\u679c\u7a0b\u5e8f\u4e2d\u9700\u8981\u540c\u65f6\u521b\u5efa\u5927\u91cf\u7684\u65e5\u671f\u5b9e\u4f8b\uff0c\u90a3\u4e48\u8fd9\u4e2a\u5c31\u80fd\u6781\u5927\u7684\u51cf\u5c0f\u5185\u5b58\u4f7f\u7528\u91cf\u4e86\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5c3d\u7ba1slots\u770b\u4e0a\u53bb\u662f\u4e00\u4e2a\u5f88\u6709\u7528\u7684\u7279\u6027\uff0c\u5f88\u591a\u65f6\u5019\u4f60\u8fd8\u662f\u5f97\u51cf\u5c11\u5bf9\u5b83\u7684\u4f7f\u7528\u51b2\u52a8\u3002\nPython\u7684\u5f88\u591a\u7279\u6027\u90fd\u4f9d\u8d56\u4e8e\u666e\u901a\u7684\u57fa\u4e8e\u5b57\u5178\u7684\u5b9e\u73b0\u3002\n\u53e6\u5916\uff0c\u5b9a\u4e49\u4e86slots\u540e\u7684\u7c7b\u4e0d\u518d\u652f\u6301\u4e00\u4e9b\u666e\u901a\u7c7b\u7279\u6027\u4e86\uff0c\u6bd4\u5982\u591a\u7ee7\u627f\u3002\n\u5927\u591a\u6570\u60c5\u51b5\u4e0b\uff0c\u4f60\u5e94\u8be5\u53ea\u5728\u90a3\u4e9b\u7ecf\u5e38\u88ab\u4f7f\u7528\u5230\u7684\u7528\u4f5c\u6570\u636e\u7ed3\u6784\u7684\u7c7b\u4e0a\u5b9a\u4e49slots\n(\u6bd4\u5982\u5728\u7a0b\u5e8f\u4e2d\u9700\u8981\u521b\u5efa\u67d0\u4e2a\u7c7b\u7684\u51e0\u767e\u4e07\u4e2a\u5b9e\u4f8b\u5bf9\u8c61)\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5173\u4e8e __slots__ \u7684\u4e00\u4e2a\u5e38\u89c1\u8bef\u533a\u662f\u5b83\u53ef\u4ee5\u4f5c\u4e3a\u4e00\u4e2a\u5c01\u88c5\u5de5\u5177\u6765\u9632\u6b62\u7528\u6237\u7ed9\u5b9e\u4f8b\u589e\u52a0\u65b0\u7684\u5c5e\u6027\u3002\n\u5c3d\u7ba1\u4f7f\u7528slots\u53ef\u4ee5\u8fbe\u5230\u8fd9\u6837\u7684\u76ee\u7684\uff0c\u4f46\u662f\u8fd9\u4e2a\u5e76\u4e0d\u662f\u5b83\u7684\u521d\u8877\u3002\n__slots__ \u66f4\u591a\u7684\u662f\u7528\u6765\u4f5c\u4e3a\u4e00\u4e2a\u5185\u5b58\u4f18\u5316\u5de5\u5177\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 8.5 \u5728\u7c7b\u4e2d\u5c01\u88c5\u5c5e\u6027\u540d\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u60f3\u5c01\u88c5\u7c7b\u7684\u5b9e\u4f8b\u4e0a\u9762\u7684\u201c\u79c1\u6709\u201d\u6570\u636e\uff0c\u4f46\u662fPython\u8bed\u8a00\u5e76\u6ca1\u6709\u8bbf\u95ee\u63a7\u5236\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Python\u7a0b\u5e8f\u5458\u4e0d\u53bb\u4f9d\u8d56\u8bed\u8a00\u7279\u6027\u53bb\u5c01\u88c5\u6570\u636e\uff0c\u800c\u662f\u901a\u8fc7\u9075\u5faa\u4e00\u5b9a\u7684\u5c5e\u6027\u548c\u65b9\u6cd5\u547d\u540d\u89c4\u7ea6\u6765\u8fbe\u5230\u8fd9\u4e2a\u6548\u679c\u3002\n\u7b2c\u4e00\u4e2a\u7ea6\u5b9a\u662f\u4efb\u4f55\u4ee5\u5355\u4e0b\u5212\u7ebf_\u5f00\u5934\u7684\u540d\u5b57\u90fd\u5e94\u8be5\u662f\u5185\u90e8\u5b9e\u73b0\u3002\u6bd4\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class A:\n    def __init__(self):\n        self._internal = 0 # An internal attribute\n        self.public = 1 # A public attribute\n\n    def public_method(self):\n        '''\n        A public method\n        '''\n        pass\n\n    def _internal_method(self):\n        pass"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Python\u5e76\u4e0d\u4f1a\u771f\u7684\u963b\u6b62\u522b\u4eba\u8bbf\u95ee\u5185\u90e8\u540d\u79f0\u3002\u4f46\u662f\u5982\u679c\u4f60\u8fd9\u4e48\u505a\u80af\u5b9a\u662f\u4e0d\u597d\u7684\uff0c\u53ef\u80fd\u4f1a\u5bfc\u81f4\u8106\u5f31\u7684\u4ee3\u7801\u3002\n\u540c\u65f6\u8fd8\u8981\u6ce8\u610f\u5230\uff0c\u4f7f\u7528\u4e0b\u5212\u7ebf\u5f00\u5934\u7684\u7ea6\u5b9a\u540c\u6837\u9002\u7528\u4e8e\u6a21\u5757\u540d\u548c\u6a21\u5757\u7ea7\u522b\u51fd\u6570\u3002\n\u4f8b\u5982\uff0c\u5982\u679c\u4f60\u770b\u5230\u67d0\u4e2a\u6a21\u5757\u540d\u4ee5\u5355\u4e0b\u5212\u7ebf\u5f00\u5934(\u6bd4\u5982_socket)\uff0c\u90a3\u5b83\u5c31\u662f\u5185\u90e8\u5b9e\u73b0\u3002\n\u7c7b\u4f3c\u7684\uff0c\u6a21\u5757\u7ea7\u522b\u51fd\u6570\u6bd4\u5982 sys._getframe() \u5728\u4f7f\u7528\u7684\u65f6\u5019\u5c31\u5f97\u52a0\u500d\u5c0f\u5fc3\u4e86\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u8fd8\u53ef\u80fd\u4f1a\u9047\u5230\u5728\u7c7b\u5b9a\u4e49\u4e2d\u4f7f\u7528\u4e24\u4e2a\u4e0b\u5212\u7ebf(__)\u5f00\u5934\u7684\u547d\u540d\u3002\u6bd4\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class B:\n    def __init__(self):\n        self.__private = 0\n\n    def __private_method(self):\n        pass\n\n    def public_method(self):\n        pass\n        self.__private_method()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f7f\u7528\u53cc\u4e0b\u5212\u7ebf\u5f00\u59cb\u4f1a\u5bfc\u81f4\u8bbf\u95ee\u540d\u79f0\u53d8\u6210\u5176\u4ed6\u5f62\u5f0f\u3002\n\u6bd4\u5982\uff0c\u5728\u524d\u9762\u7684\u7c7bB\u4e2d\uff0c\u79c1\u6709\u5c5e\u6027\u4f1a\u88ab\u5206\u522b\u91cd\u547d\u540d\u4e3a _B__private \u548c _B__private_method \u3002\n\u8fd9\u65f6\u5019\u4f60\u53ef\u80fd\u4f1a\u95ee\u8fd9\u6837\u91cd\u547d\u540d\u7684\u76ee\u7684\u662f\u4ec0\u4e48\uff0c\u7b54\u6848\u5c31\u662f\u7ee7\u627f\u2014\u2014\u8fd9\u79cd\u5c5e\u6027\u901a\u8fc7\u7ee7\u627f\u662f\u65e0\u6cd5\u88ab\u8986\u76d6\u7684\u3002\u6bd4\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class C(B):\n    def __init__(self):\n        super().__init__()\n        self.__private = 1 # Does not override B.__private\n\n    # Does not override B.__private_method()\n    def __private_method(self):\n        pass"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u91cc\uff0c\u79c1\u6709\u540d\u79f0 __private \u548c __private_method\n\u88ab\u91cd\u547d\u540d\u4e3a _C__private \u548c _C__private_method \uff0c\u8fd9\u4e2a\u8ddf\u7236\u7c7bB\u4e2d\u7684\u540d\u79f0\u662f\u5b8c\u5168\u4e0d\u540c\u7684\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e0a\u9762\u63d0\u5230\u6709\u4e24\u79cd\u4e0d\u540c\u7684\u7f16\u7801\u7ea6\u5b9a(\u5355\u4e0b\u5212\u7ebf\u548c\u53cc\u4e0b\u5212\u7ebf)\u6765\u547d\u540d\u79c1\u6709\u5c5e\u6027\uff0c\u90a3\u4e48\u95ee\u9898\u5c31\u6765\u4e86\uff1a\u5230\u5e95\u54ea\u79cd\u65b9\u5f0f\u597d\u5462\uff1f\n\u5927\u591a\u6570\u800c\u8a00\uff0c\u4f60\u5e94\u8be5\u8ba9\u4f60\u7684\u975e\u516c\u5171\u540d\u79f0\u4ee5\u5355\u4e0b\u5212\u7ebf\u5f00\u5934\u3002\u4f46\u662f\uff0c\u5982\u679c\u4f60\u6e05\u695a\u4f60\u7684\u4ee3\u7801\u4f1a\u6d89\u53ca\u5230\u5b50\u7c7b\uff0c\n\u5e76\u4e14\u6709\u4e9b\u5185\u90e8\u5c5e\u6027\u5e94\u8be5\u5728\u5b50\u7c7b\u4e2d\u9690\u85cf\u8d77\u6765\uff0c\u90a3\u4e48\u624d\u8003\u8651\u4f7f\u7528\u53cc\u4e0b\u5212\u7ebf\u65b9\u6848\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd8\u6709\u4e00\u70b9\u8981\u6ce8\u610f\u7684\u662f\uff0c\u6709\u65f6\u5019\u4f60\u5b9a\u4e49\u7684\u4e00\u4e2a\u53d8\u91cf\u548c\u67d0\u4e2a\u4fdd\u7559\u5173\u952e\u5b57\u51b2\u7a81\uff0c\u8fd9\u65f6\u5019\u53ef\u4ee5\u4f7f\u7528\u5355\u4e0b\u5212\u7ebf\u4f5c\u4e3a\u540e\u7f00\uff0c\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "lambda_ = 2.0 # Trailing _ to avoid clash with lambda keyword"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u91cc\u6211\u4eec\u5e76\u4e0d\u4f7f\u7528\u5355\u4e0b\u5212\u7ebf\u524d\u7f00\u7684\u539f\u56e0\u662f\u5b83\u907f\u514d\u8bef\u89e3\u5b83\u7684\u4f7f\u7528\u521d\u8877\n(\u5982\u4f7f\u7528\u5355\u4e0b\u5212\u7ebf\u524d\u7f00\u7684\u76ee\u7684\u662f\u4e3a\u4e86\u9632\u6b62\u547d\u540d\u51b2\u7a81\u800c\u4e0d\u662f\u6307\u660e\u8fd9\u4e2a\u5c5e\u6027\u662f\u79c1\u6709\u7684)\u3002\n\u901a\u8fc7\u4f7f\u7528\u5355\u4e0b\u5212\u7ebf\u540e\u7f00\u53ef\u4ee5\u89e3\u51b3\u8fd9\u4e2a\u95ee\u9898\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 8.6 \u521b\u5efa\u53ef\u7ba1\u7406\u7684\u5c5e\u6027\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u60f3\u7ed9\u67d0\u4e2a\u5b9e\u4f8battribute\u589e\u52a0\u9664\u8bbf\u95ee\u4e0e\u4fee\u6539\u4e4b\u5916\u7684\u5176\u4ed6\u5904\u7406\u903b\u8f91\uff0c\u6bd4\u5982\u7c7b\u578b\u68c0\u67e5\u6216\u5408\u6cd5\u6027\u9a8c\u8bc1\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u81ea\u5b9a\u4e49\u67d0\u4e2a\u5c5e\u6027\u7684\u4e00\u79cd\u7b80\u5355\u65b9\u6cd5\u662f\u5c06\u5b83\u5b9a\u4e49\u4e3a\u4e00\u4e2aproperty\u3002\n\u4f8b\u5982\uff0c\u4e0b\u9762\u7684\u4ee3\u7801\u5b9a\u4e49\u4e86\u4e00\u4e2aproperty\uff0c\u589e\u52a0\u5bf9\u4e00\u4e2a\u5c5e\u6027\u7b80\u5355\u7684\u7c7b\u578b\u68c0\u67e5\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class Person:\n    def __init__(self, first_name):\n        self._first_name = first_name\n\n    # Getter function\n    @property\n    def first_name(self):\n        return self._first_name\n\n    # Setter function\n    @first_name.setter\n    def first_name(self, value):\n        if not isinstance(value, str):\n            raise TypeError('Expected a string')\n        self._first_name = value\n\n    # Deleter function (optional)\n    @first_name.deleter\n    def first_name(self):\n        raise AttributeError(\"Can't delete attribute\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e0a\u8ff0\u4ee3\u7801\u4e2d\u6709\u4e09\u4e2a\u76f8\u5173\u8054\u7684\u65b9\u6cd5\uff0c\u8fd9\u4e09\u4e2a\u65b9\u6cd5\u7684\u540d\u5b57\u90fd\u5fc5\u987b\u4e00\u6837\u3002\n\u7b2c\u4e00\u4e2a\u65b9\u6cd5\u662f\u4e00\u4e2a getter \u51fd\u6570\uff0c\u5b83\u4f7f\u5f97 first_name \u6210\u4e3a\u4e00\u4e2a\u5c5e\u6027\u3002\n\u5176\u4ed6\u4e24\u4e2a\u65b9\u6cd5\u7ed9 first_name \u5c5e\u6027\u6dfb\u52a0\u4e86 setter \u548c deleter \u51fd\u6570\u3002\n\u9700\u8981\u5f3a\u8c03\u7684\u662f\u53ea\u6709\u5728 first_name \u5c5e\u6027\u88ab\u521b\u5efa\u540e\uff0c\n\u540e\u9762\u7684\u4e24\u4e2a\u88c5\u9970\u5668 @first_name.setter \u548c @first_name.deleter \u624d\u80fd\u88ab\u5b9a\u4e49\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "property\u7684\u4e00\u4e2a\u5173\u952e\u7279\u5f81\u662f\u5b83\u770b\u4e0a\u53bb\u8ddf\u666e\u901a\u7684attribute\u6ca1\u4ec0\u4e48\u4e24\u6837\uff0c\n\u4f46\u662f\u8bbf\u95ee\u5b83\u7684\u65f6\u5019\u4f1a\u81ea\u52a8\u89e6\u53d1 getter \u3001setter \u548c deleter \u65b9\u6cd5\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "a = Person('Guido')\na.first_name # Calls the getter"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "a.first_name = 42 # Calls the setter"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "del a.first_name"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5728\u5b9e\u73b0\u4e00\u4e2aproperty\u7684\u65f6\u5019\uff0c\u5e95\u5c42\u6570\u636e(\u5982\u679c\u6709\u7684\u8bdd)\u4ecd\u7136\u9700\u8981\u5b58\u50a8\u5728\u67d0\u4e2a\u5730\u65b9\u3002\n\u56e0\u6b64\uff0c\u5728get\u548cset\u65b9\u6cd5\u4e2d\uff0c\u4f60\u4f1a\u770b\u5230\u5bf9 _first_name \u5c5e\u6027\u7684\u64cd\u4f5c\uff0c\u8fd9\u4e5f\u662f\u5b9e\u9645\u6570\u636e\u4fdd\u5b58\u7684\u5730\u65b9\u3002\n\u53e6\u5916\uff0c\u4f60\u53ef\u80fd\u8fd8\u4f1a\u95ee\u4e3a\u4ec0\u4e48 __init__() \u65b9\u6cd5\u4e2d\u8bbe\u7f6e\u4e86 self.first_name \u800c\u4e0d\u662f self._first_name \u3002\n\u5728\u8fd9\u4e2a\u4f8b\u5b50\u4e2d\uff0c\u6211\u4eec\u521b\u5efa\u4e00\u4e2aproperty\u7684\u76ee\u7684\u5c31\u662f\u5728\u8bbe\u7f6eattribute\u7684\u65f6\u5019\u8fdb\u884c\u68c0\u67e5\u3002\n\u56e0\u6b64\uff0c\u4f60\u53ef\u80fd\u60f3\u5728\u521d\u59cb\u5316\u7684\u65f6\u5019\u4e5f\u8fdb\u884c\u8fd9\u79cd\u7c7b\u578b\u68c0\u67e5\u3002\u901a\u8fc7\u8bbe\u7f6e self.first_name \uff0c\u81ea\u52a8\u8c03\u7528 setter \u65b9\u6cd5\uff0c\n\u8fd9\u4e2a\u65b9\u6cd5\u91cc\u9762\u4f1a\u8fdb\u884c\u53c2\u6570\u7684\u68c0\u67e5\uff0c\u5426\u5219\u5c31\u662f\u76f4\u63a5\u8bbf\u95ee self._first_name \u4e86\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd8\u80fd\u5728\u5df2\u5b58\u5728\u7684get\u548cset\u65b9\u6cd5\u57fa\u7840\u4e0a\u5b9a\u4e49property\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class Person:\n    def __init__(self, first_name):\n        self.set_first_name(first_name)\n\n    # Getter function\n    def get_first_name(self):\n        return self._first_name\n\n    # Setter function\n    def set_first_name(self, value):\n        if not isinstance(value, str):\n            raise TypeError('Expected a string')\n        self._first_name = value\n\n    # Deleter function (optional)\n    def del_first_name(self):\n        raise AttributeError(\"Can't delete attribute\")\n\n    # Make a property from existing get/set methods\n    name = property(get_first_name, set_first_name, del_first_name)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e00\u4e2aproperty\u5c5e\u6027\u5176\u5b9e\u5c31\u662f\u4e00\u7cfb\u5217\u76f8\u5173\u7ed1\u5b9a\u65b9\u6cd5\u7684\u96c6\u5408\u3002\u5982\u679c\u4f60\u53bb\u67e5\u770b\u62e5\u6709property\u7684\u7c7b\uff0c\n\u5c31\u4f1a\u53d1\u73b0property\u672c\u8eab\u7684fget\u3001fset\u548cfdel\u5c5e\u6027\u5c31\u662f\u7c7b\u91cc\u9762\u7684\u666e\u901a\u65b9\u6cd5\u3002\u6bd4\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "Person.first_name.fget"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "Person.first_name.fset"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "Person.first_name.fdel"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u901a\u5e38\u6765\u8bb2\uff0c\u4f60\u4e0d\u4f1a\u76f4\u63a5\u53d6\u8c03\u7528fget\u6216\u8005fset\uff0c\u5b83\u4eec\u4f1a\u5728\u8bbf\u95eeproperty\u7684\u65f6\u5019\u81ea\u52a8\u88ab\u89e6\u53d1\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u53ea\u6709\u5f53\u4f60\u786e\u5b9e\u9700\u8981\u5bf9attribute\u6267\u884c\u5176\u4ed6\u989d\u5916\u7684\u64cd\u4f5c\u7684\u65f6\u5019\u624d\u5e94\u8be5\u4f7f\u7528\u5230property\u3002\n\u6709\u65f6\u5019\u4e00\u4e9b\u4ece\u5176\u4ed6\u7f16\u7a0b\u8bed\u8a00(\u6bd4\u5982Java)\u8fc7\u6765\u7684\u7a0b\u5e8f\u5458\u603b\u8ba4\u4e3a\u6240\u6709\u8bbf\u95ee\u90fd\u5e94\u8be5\u901a\u8fc7getter\u548csetter\uff0c\n\u6240\u4ee5\u4ed6\u4eec\u8ba4\u4e3a\u4ee3\u7801\u5e94\u8be5\u50cf\u4e0b\u9762\u8fd9\u6837\u5199\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class Person:\n    def __init__(self, first_name):\n        self.first_name = first_name\n\n    @property\n    def first_name(self):\n        return self._first_name\n\n    @first_name.setter\n    def first_name(self, value):\n        self._first_name = value"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e0d\u8981\u5199\u8fd9\u79cd\u6ca1\u6709\u505a\u4efb\u4f55\u5176\u4ed6\u989d\u5916\u64cd\u4f5c\u7684property\u3002\n\u9996\u5148\uff0c\u5b83\u4f1a\u8ba9\u4f60\u7684\u4ee3\u7801\u53d8\u5f97\u5f88\u81c3\u80bf\uff0c\u5e76\u4e14\u8fd8\u4f1a\u8ff7\u60d1\u9605\u8bfb\u8005\u3002\n\u5176\u6b21\uff0c\u5b83\u8fd8\u4f1a\u8ba9\u4f60\u7684\u7a0b\u5e8f\u8fd0\u884c\u8d77\u6765\u53d8\u6162\u5f88\u591a\u3002\n\u6700\u540e\uff0c\u8fd9\u6837\u7684\u8bbe\u8ba1\u5e76\u6ca1\u6709\u5e26\u6765\u4efb\u4f55\u7684\u597d\u5904\u3002\n\u7279\u522b\u662f\u5f53\u4f60\u4ee5\u540e\u60f3\u7ed9\u666e\u901aattribute\u8bbf\u95ee\u6dfb\u52a0\u989d\u5916\u7684\u5904\u7406\u903b\u8f91\u7684\u65f6\u5019\uff0c\n\u4f60\u53ef\u4ee5\u5c06\u5b83\u53d8\u6210\u4e00\u4e2aproperty\u800c\u65e0\u9700\u6539\u53d8\u539f\u6765\u7684\u4ee3\u7801\u3002\n\u56e0\u4e3a\u8bbf\u95eeattribute\u7684\u4ee3\u7801\u8fd8\u662f\u4fdd\u6301\u539f\u6837\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Properties\u8fd8\u662f\u4e00\u79cd\u5b9a\u4e49\u52a8\u6001\u8ba1\u7b97attribute\u7684\u65b9\u6cd5\u3002\n\u8fd9\u79cd\u7c7b\u578b\u7684attributes\u5e76\u4e0d\u4f1a\u88ab\u5b9e\u9645\u7684\u5b58\u50a8\uff0c\u800c\u662f\u5728\u9700\u8981\u7684\u65f6\u5019\u8ba1\u7b97\u51fa\u6765\u3002\u6bd4\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import math\nclass Circle:\n    def __init__(self, radius):\n        self.radius = radius\n\n    @property\n    def area(self):\n        return math.pi * self.radius ** 2\n\n    @property\n    def diameter(self):\n        return self.radius * 2\n\n    @property\n    def perimeter(self):\n        return 2 * math.pi * self.radius"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5728\u8fd9\u91cc\uff0c\u6211\u4eec\u901a\u8fc7\u4f7f\u7528properties\uff0c\u5c06\u6240\u6709\u7684\u8bbf\u95ee\u63a5\u53e3\u5f62\u5f0f\u7edf\u4e00\u8d77\u6765\uff0c\n\u5bf9\u534a\u5f84\u3001\u76f4\u5f84\u3001\u5468\u957f\u548c\u9762\u79ef\u7684\u8bbf\u95ee\u90fd\u662f\u901a\u8fc7\u5c5e\u6027\u8bbf\u95ee\uff0c\u5c31\u8ddf\u8bbf\u95ee\u7b80\u5355\u7684attribute\u662f\u4e00\u6837\u7684\u3002\n\u5982\u679c\u4e0d\u8fd9\u6837\u505a\u7684\u8bdd\uff0c\u90a3\u4e48\u5c31\u8981\u5728\u4ee3\u7801\u4e2d\u6df7\u5408\u4f7f\u7528\u7b80\u5355\u5c5e\u6027\u8bbf\u95ee\u548c\u65b9\u6cd5\u8c03\u7528\u3002\n\u4e0b\u9762\u662f\u4f7f\u7528\u7684\u5b9e\u4f8b\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "c = Circle(4.0)\nc.radius"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "c.area  # Notice lack of ()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "c.perimeter  # Notice lack of ()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5c3d\u7ba1properties\u53ef\u4ee5\u5b9e\u73b0\u4f18\u96c5\u7684\u7f16\u7a0b\u63a5\u53e3\uff0c\u4f46\u6709\u4e9b\u65f6\u5019\u4f60\u8fd8\u662f\u4f1a\u60f3\u76f4\u63a5\u4f7f\u7528getter\u548csetter\u51fd\u6570\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "p = Person('Guido')\np.get_first_name()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "p.set_first_name('Larry')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u79cd\u60c5\u51b5\u7684\u51fa\u73b0\u901a\u5e38\u662f\u56e0\u4e3aPython\u4ee3\u7801\u88ab\u96c6\u6210\u5230\u4e00\u4e2a\u5927\u578b\u57fa\u7840\u5e73\u53f0\u67b6\u6784\u6216\u7a0b\u5e8f\u4e2d\u3002\n\u4f8b\u5982\uff0c\u6709\u53ef\u80fd\u662f\u4e00\u4e2aPython\u7c7b\u51c6\u5907\u52a0\u5165\u5230\u4e00\u4e2a\u57fa\u4e8e\u8fdc\u7a0b\u8fc7\u7a0b\u8c03\u7528\u7684\u5927\u578b\u5206\u5e03\u5f0f\u7cfb\u7edf\u4e2d\u3002\n\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u76f4\u63a5\u4f7f\u7528get/set\u65b9\u6cd5(\u666e\u901a\u65b9\u6cd5\u8c03\u7528)\u800c\u4e0d\u662fproperty\u6216\u8bb8\u4f1a\u66f4\u5bb9\u6613\u517c\u5bb9\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u6700\u540e\u4e00\u70b9\uff0c\u4e0d\u8981\u50cf\u4e0b\u9762\u8fd9\u6837\u5199\u6709\u5927\u91cf\u91cd\u590d\u4ee3\u7801\u7684property\u5b9a\u4e49\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class Person:\n    def __init__(self, first_name, last_name):\n        self.first_name = first_name\n        self.last_name = last_name\n\n    @property\n    def first_name(self):\n        return self._first_name\n\n    @first_name.setter\n    def first_name(self, value):\n        if not isinstance(value, str):\n            raise TypeError('Expected a string')\n        self._first_name = value\n\n    # Repeated property code, but for a different name (bad!)\n    @property\n    def last_name(self):\n        return self._last_name\n\n    @last_name.setter\n    def last_name(self, value):\n        if not isinstance(value, str):\n            raise TypeError('Expected a string')\n        self._last_name = value"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u91cd\u590d\u4ee3\u7801\u4f1a\u5bfc\u81f4\u81c3\u80bf\u3001\u6613\u51fa\u9519\u548c\u4e11\u964b\u7684\u7a0b\u5e8f\u3002\u597d\u6d88\u606f\u662f\uff0c\u901a\u8fc7\u4f7f\u7528\u88c5\u9970\u5668\u6216\u95ed\u5305\uff0c\u6709\u5f88\u591a\u79cd\u66f4\u597d\u7684\u65b9\u6cd5\u6765\u5b8c\u6210\u540c\u6837\u7684\u4e8b\u60c5\u3002\n\u53ef\u4ee5\u53c2\u80038.9\u548c9.21\u5c0f\u8282\u7684\u5185\u5bb9\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 8.7 \u8c03\u7528\u7236\u7c7b\u65b9\u6cd5\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u60f3\u5728\u5b50\u7c7b\u4e2d\u8c03\u7528\u7236\u7c7b\u7684\u67d0\u4e2a\u5df2\u7ecf\u88ab\u8986\u76d6\u7684\u65b9\u6cd5\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e3a\u4e86\u8c03\u7528\u7236\u7c7b(\u8d85\u7c7b)\u7684\u4e00\u4e2a\u65b9\u6cd5\uff0c\u53ef\u4ee5\u4f7f\u7528 super() \u51fd\u6570\uff0c\u6bd4\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class A:\n    def spam(self):\n        print('A.spam')\n\nclass B(A):\n    def spam(self):\n        print('B.spam')\n        super().spam()  # Call parent spam()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "super() \u51fd\u6570\u7684\u4e00\u4e2a\u5e38\u89c1\u7528\u6cd5\u662f\u5728 __init__() \u65b9\u6cd5\u4e2d\u786e\u4fdd\u7236\u7c7b\u88ab\u6b63\u786e\u7684\u521d\u59cb\u5316\u4e86\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class A:\n    def __init__(self):\n        self.x = 0\n\nclass B(A):\n    def __init__(self):\n        super().__init__()\n        self.y = 1"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "super() \u7684\u53e6\u5916\u4e00\u4e2a\u5e38\u89c1\u7528\u6cd5\u51fa\u73b0\u5728\u8986\u76d6Python\u7279\u6b8a\u65b9\u6cd5\u7684\u4ee3\u7801\u4e2d\uff0c\u6bd4\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class Proxy:\n    def __init__(self, obj):\n        self._obj = obj\n\n    # Delegate attribute lookup to internal obj\n    def __getattr__(self, name):\n        return getattr(self._obj, name)\n\n    # Delegate attribute assignment\n    def __setattr__(self, name, value):\n        if name.startswith('_'):\n            super().__setattr__(name, value) # Call original __setattr__\n        else:\n            setattr(self._obj, name, value)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5728\u4e0a\u9762\u4ee3\u7801\u4e2d\uff0c__setattr__() \u7684\u5b9e\u73b0\u5305\u542b\u4e00\u4e2a\u540d\u5b57\u68c0\u67e5\u3002\n\u5982\u679c\u67d0\u4e2a\u5c5e\u6027\u540d\u4ee5\u4e0b\u5212\u7ebf(_)\u5f00\u5934\uff0c\u5c31\u901a\u8fc7 super() \u8c03\u7528\u539f\u59cb\u7684 __setattr__() \uff0c\n\u5426\u5219\u7684\u8bdd\u5c31\u59d4\u6d3e\u7ed9\u5185\u90e8\u7684\u4ee3\u7406\u5bf9\u8c61 self._obj \u53bb\u5904\u7406\u3002\n\u8fd9\u770b\u4e0a\u53bb\u6709\u70b9\u610f\u601d\uff0c\u56e0\u4e3a\u5c31\u7b97\u6ca1\u6709\u663e\u5f0f\u7684\u6307\u660e\u67d0\u4e2a\u7c7b\u7684\u7236\u7c7b\uff0c super() \u4ecd\u7136\u53ef\u4ee5\u6709\u6548\u7684\u5de5\u4f5c\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5b9e\u9645\u4e0a\uff0c\u5927\u5bb6\u5bf9\u4e8e\u5728Python\u4e2d\u5982\u4f55\u6b63\u786e\u4f7f\u7528 super() \u51fd\u6570\u666e\u904d\u77e5\u4e4b\u751a\u5c11\u3002\n\u4f60\u6709\u65f6\u5019\u4f1a\u770b\u5230\u50cf\u4e0b\u9762\u8fd9\u6837\u76f4\u63a5\u8c03\u7528\u7236\u7c7b\u7684\u4e00\u4e2a\u65b9\u6cd5\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class Base:\n    def __init__(self):\n        print('Base.__init__')\n\nclass A(Base):\n    def __init__(self):\n        Base.__init__(self)\n        print('A.__init__')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5c3d\u7ba1\u5bf9\u4e8e\u5927\u90e8\u5206\u4ee3\u7801\u800c\u8a00\u8fd9\u4e48\u505a\u6ca1\u4ec0\u4e48\u95ee\u9898\uff0c\u4f46\u662f\u5728\u66f4\u590d\u6742\u7684\u6d89\u53ca\u5230\u591a\u7ee7\u627f\u7684\u4ee3\u7801\u4e2d\u5c31\u6709\u53ef\u80fd\u5bfc\u81f4\u5f88\u5947\u602a\u7684\u95ee\u9898\u53d1\u751f\u3002\n\u6bd4\u5982\uff0c\u8003\u8651\u5982\u4e0b\u7684\u60c5\u51b5\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class Base:\n    def __init__(self):\n        print('Base.__init__')\n\nclass A(Base):\n    def __init__(self):\n        Base.__init__(self)\n        print('A.__init__')\n\nclass B(Base):\n    def __init__(self):\n        Base.__init__(self)\n        print('B.__init__')\n\nclass C(A,B):\n    def __init__(self):\n        A.__init__(self)\n        B.__init__(self)\n        print('C.__init__')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u4f60\u8fd0\u884c\u8fd9\u6bb5\u4ee3\u7801\u5c31\u4f1a\u53d1\u73b0 Base.__init__() \u88ab\u8c03\u7528\u4e24\u6b21\uff0c\u5982\u4e0b\u6240\u793a\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "c = C()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u53ef\u80fd\u4e24\u6b21\u8c03\u7528 Base.__init__() \u6ca1\u4ec0\u4e48\u574f\u5904\uff0c\u4f46\u6709\u65f6\u5019\u5374\u4e0d\u662f\u3002\n\u53e6\u4e00\u65b9\u9762\uff0c\u5047\u8bbe\u4f60\u5728\u4ee3\u7801\u4e2d\u6362\u6210\u4f7f\u7528 super() \uff0c\u7ed3\u679c\u5c31\u5f88\u5b8c\u7f8e\u4e86\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class Base:\n    def __init__(self):\n        print('Base.__init__')\n\nclass A(Base):\n    def __init__(self):\n        super().__init__()\n        print('A.__init__')\n\nclass B(Base):\n    def __init__(self):\n        super().__init__()\n        print('B.__init__')\n\nclass C(A,B):\n    def __init__(self):\n        super().__init__()  # Only one call to super() here\n        print('C.__init__')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd0\u884c\u8fd9\u4e2a\u65b0\u7248\u672c\u540e\uff0c\u4f60\u4f1a\u53d1\u73b0\u6bcf\u4e2a __init__() \u65b9\u6cd5\u53ea\u4f1a\u88ab\u8c03\u7528\u4e00\u6b21\u4e86\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "c = C()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e3a\u4e86\u5f04\u6e05\u5b83\u7684\u539f\u7406\uff0c\u6211\u4eec\u9700\u8981\u82b1\u70b9\u65f6\u95f4\u89e3\u91ca\u4e0bPython\u662f\u5982\u4f55\u5b9e\u73b0\u7ee7\u627f\u7684\u3002\n\u5bf9\u4e8e\u4f60\u5b9a\u4e49\u7684\u6bcf\u4e00\u4e2a\u7c7b\uff0cPython\u4f1a\u8ba1\u7b97\u51fa\u4e00\u4e2a\u6240\u8c13\u7684\u65b9\u6cd5\u89e3\u6790\u987a\u5e8f(MRO)\u5217\u8868\u3002\n\u8fd9\u4e2aMRO\u5217\u8868\u5c31\u662f\u4e00\u4e2a\u7b80\u5355\u7684\u6240\u6709\u57fa\u7c7b\u7684\u7ebf\u6027\u987a\u5e8f\u8868\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "C.__mro__"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e3a\u4e86\u5b9e\u73b0\u7ee7\u627f\uff0cPython\u4f1a\u5728MRO\u5217\u8868\u4e0a\u4ece\u5de6\u5230\u53f3\u5f00\u59cb\u67e5\u627e\u57fa\u7c7b\uff0c\u76f4\u5230\u627e\u5230\u7b2c\u4e00\u4e2a\u5339\u914d\u8fd9\u4e2a\u5c5e\u6027\u7684\u7c7b\u4e3a\u6b62\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u800c\u8fd9\u4e2aMRO\u5217\u8868\u7684\u6784\u9020\u662f\u901a\u8fc7\u4e00\u4e2aC3\u7ebf\u6027\u5316\u7b97\u6cd5\u6765\u5b9e\u73b0\u7684\u3002\n\u6211\u4eec\u4e0d\u53bb\u6df1\u7a76\u8fd9\u4e2a\u7b97\u6cd5\u7684\u6570\u5b66\u539f\u7406\uff0c\u5b83\u5b9e\u9645\u4e0a\u5c31\u662f\u5408\u5e76\u6240\u6709\u7236\u7c7b\u7684MRO\u5217\u8868\u5e76\u9075\u5faa\u5982\u4e0b\u4e09\u6761\u51c6\u5219\uff1a"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8001\u5b9e\u8bf4\uff0c\u4f60\u6240\u8981\u77e5\u9053\u7684\u5c31\u662fMRO\u5217\u8868\u4e2d\u7684\u7c7b\u987a\u5e8f\u4f1a\u8ba9\u4f60\u5b9a\u4e49\u7684\u4efb\u610f\u7c7b\u5c42\u7ea7\u5173\u7cfb\u53d8\u5f97\u6709\u610f\u4e49\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5f53\u4f60\u4f7f\u7528 super() \u51fd\u6570\u65f6\uff0cPython\u4f1a\u5728MRO\u5217\u8868\u4e0a\u7ee7\u7eed\u641c\u7d22\u4e0b\u4e00\u4e2a\u7c7b\u3002\n\u53ea\u8981\u6bcf\u4e2a\u91cd\u5b9a\u4e49\u7684\u65b9\u6cd5\u7edf\u4e00\u4f7f\u7528 super() \u5e76\u53ea\u8c03\u7528\u5b83\u4e00\u6b21\uff0c\n\u90a3\u4e48\u63a7\u5236\u6d41\u6700\u7ec8\u4f1a\u904d\u5386\u5b8c\u6574\u4e2aMRO\u5217\u8868\uff0c\u6bcf\u4e2a\u65b9\u6cd5\u4e5f\u53ea\u4f1a\u88ab\u8c03\u7528\u4e00\u6b21\u3002\n\u8fd9\u4e5f\u662f\u4e3a\u4ec0\u4e48\u5728\u7b2c\u4e8c\u4e2a\u4f8b\u5b50\u4e2d\u4f60\u4e0d\u4f1a\u8c03\u7528\u4e24\u6b21 Base.__init__() \u7684\u539f\u56e0\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "super() \u6709\u4e2a\u4ee4\u4eba\u5403\u60ca\u7684\u5730\u65b9\u662f\u5b83\u5e76\u4e0d\u4e00\u5b9a\u53bb\u67e5\u627e\u67d0\u4e2a\u7c7b\u5728MRO\u4e2d\u4e0b\u4e00\u4e2a\u76f4\u63a5\u7236\u7c7b\uff0c\n\u4f60\u751a\u81f3\u53ef\u4ee5\u5728\u4e00\u4e2a\u6ca1\u6709\u76f4\u63a5\u7236\u7c7b\u7684\u7c7b\u4e2d\u4f7f\u7528\u5b83\u3002\u4f8b\u5982\uff0c\u8003\u8651\u5982\u4e0b\u8fd9\u4e2a\u7c7b\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class A:\n    def spam(self):\n        print('A.spam')\n        super().spam()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u4f60\u8bd5\u7740\u76f4\u63a5\u4f7f\u7528\u8fd9\u4e2a\u7c7b\u5c31\u4f1a\u51fa\u9519\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "a = A()\na.spam()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f46\u662f\uff0c\u5982\u679c\u4f60\u4f7f\u7528\u591a\u7ee7\u627f\u7684\u8bdd\u770b\u770b\u4f1a\u53d1\u751f\u4ec0\u4e48\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class B:\n    def spam(self):\n        print('B.spam')\nclass C(A,B):\n    pass\nc = C()\nc.spam()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u53ef\u4ee5\u770b\u5230\u5728\u7c7bA\u4e2d\u4f7f\u7528 super().spam() \u5b9e\u9645\u4e0a\u8c03\u7528\u7684\u662f\u8ddf\u7c7bA\u6beb\u65e0\u5173\u7cfb\u7684\u7c7bB\u4e2d\u7684 spam() \u65b9\u6cd5\u3002\n\u8fd9\u4e2a\u7528\u7c7bC\u7684MRO\u5217\u8868\u5c31\u53ef\u4ee5\u5b8c\u5168\u89e3\u91ca\u6e05\u695a\u4e86\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "C.__mro__"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5728\u5b9a\u4e49\u6df7\u5165\u7c7b\u7684\u65f6\u5019\u8fd9\u6837\u4f7f\u7528 super() \u662f\u5f88\u666e\u904d\u7684\u3002\u53ef\u4ee5\u53c2\u80038.13\u548c8.18\u5c0f\u8282\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u7136\u800c\uff0c\u7531\u4e8e super() \u53ef\u80fd\u4f1a\u8c03\u7528\u4e0d\u662f\u4f60\u60f3\u8981\u7684\u65b9\u6cd5\uff0c\u4f60\u5e94\u8be5\u9075\u5faa\u4e00\u4e9b\u901a\u7528\u539f\u5219\u3002\n\u9996\u5148\uff0c\u786e\u4fdd\u5728\u7ee7\u627f\u4f53\u7cfb\u4e2d\u6240\u6709\u76f8\u540c\u540d\u5b57\u7684\u65b9\u6cd5\u62e5\u6709\u53ef\u517c\u5bb9\u7684\u53c2\u6570\u7b7e\u540d(\u6bd4\u5982\u76f8\u540c\u7684\u53c2\u6570\u4e2a\u6570\u548c\u53c2\u6570\u540d\u79f0)\u3002\n\u8fd9\u6837\u53ef\u4ee5\u786e\u4fdd super() \u8c03\u7528\u4e00\u4e2a\u975e\u76f4\u63a5\u7236\u7c7b\u65b9\u6cd5\u65f6\u4e0d\u4f1a\u51fa\u9519\u3002\n\u5176\u6b21\uff0c\u6700\u597d\u786e\u4fdd\u6700\u9876\u5c42\u7684\u7c7b\u63d0\u4f9b\u4e86\u8fd9\u4e2a\u65b9\u6cd5\u7684\u5b9e\u73b0\uff0c\u8fd9\u6837\u7684\u8bdd\u5728MRO\u4e0a\u9762\u7684\u67e5\u627e\u94fe\u80af\u5b9a\u53ef\u4ee5\u627e\u5230\u67d0\u4e2a\u786e\u5b9a\u7684\u65b9\u6cd5\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5728Python\u793e\u533a\u4e2d\u5bf9\u4e8e super() \u7684\u4f7f\u7528\u6709\u65f6\u5019\u4f1a\u5f15\u6765\u4e00\u4e9b\u4e89\u8bae\u3002\n\u5c3d\u7ba1\u5982\u6b64\uff0c\u5982\u679c\u4e00\u5207\u987a\u5229\u7684\u8bdd\uff0c\u4f60\u5e94\u8be5\u5728\u4f60\u6700\u65b0\u4ee3\u7801\u4e2d\u4f7f\u7528\u5b83\u3002\nRaymond Hettinger\u4e3a\u6b64\u5199\u4e86\u4e00\u7bc7\u975e\u5e38\u597d\u7684\u6587\u7ae0\n\u201cPython\u2019s super() Considered Super!\u201d \uff0c\n\u901a\u8fc7\u5927\u91cf\u7684\u4f8b\u5b50\u5411\u6211\u4eec\u89e3\u91ca\u4e86\u4e3a\u4ec0\u4e48 super() \u662f\u6781\u597d\u7684\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 8.8 \u5b50\u7c7b\u4e2d\u6269\u5c55property\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5728\u5b50\u7c7b\u4e2d\uff0c\u4f60\u60f3\u8981\u6269\u5c55\u5b9a\u4e49\u5728\u7236\u7c7b\u4e2d\u7684property\u7684\u529f\u80fd\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8003\u8651\u5982\u4e0b\u7684\u4ee3\u7801\uff0c\u5b83\u5b9a\u4e49\u4e86\u4e00\u4e2aproperty\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class Person:\n    def __init__(self, name):\n        self.name = name\n\n    # Getter function\n    @property\n    def name(self):\n        return self._name\n\n    # Setter function\n    @name.setter\n    def name(self, value):\n        if not isinstance(value, str):\n            raise TypeError('Expected a string')\n        self._name = value\n\n    # Deleter function\n    @name.deleter\n    def name(self):\n        raise AttributeError(\"Can't delete attribute\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e0b\u9762\u662f\u4e00\u4e2a\u793a\u4f8b\u7c7b\uff0c\u5b83\u7ee7\u627f\u81eaPerson\u5e76\u6269\u5c55\u4e86 name \u5c5e\u6027\u7684\u529f\u80fd\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class SubPerson(Person):\n    @property\n    def name(self):\n        print('Getting name')\n        return super().name\n\n    @name.setter\n    def name(self, value):\n        print('Setting name to', value)\n        super(SubPerson, SubPerson).name.__set__(self, value)\n\n    @name.deleter\n    def name(self):\n        print('Deleting name')\n        super(SubPerson, SubPerson).name.__delete__(self)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u63a5\u4e0b\u6765\u4f7f\u7528\u8fd9\u4e2a\u65b0\u7c7b\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "s = SubPerson('Guido')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "s.name"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "s.name = 'Larry'"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "s.name = 42"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u4f60\u4ec5\u4ec5\u53ea\u60f3\u6269\u5c55property\u7684\u67d0\u4e00\u4e2a\u65b9\u6cd5\uff0c\u90a3\u4e48\u53ef\u4ee5\u50cf\u4e0b\u9762\u8fd9\u6837\u5199\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class SubPerson(Person):\n    @Person.name.getter\n    def name(self):\n        print('Getting name')\n        return super().name"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u6216\u8005\uff0c\u4f60\u53ea\u60f3\u4fee\u6539setter\u65b9\u6cd5\uff0c\u5c31\u8fd9\u4e48\u5199\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class SubPerson(Person):\n    @Person.name.setter\n    def name(self, value):\n        print('Setting name to', value)\n        super(SubPerson, SubPerson).name.__set__(self, value)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5728\u5b50\u7c7b\u4e2d\u6269\u5c55\u4e00\u4e2aproperty\u53ef\u80fd\u4f1a\u5f15\u8d77\u5f88\u591a\u4e0d\u6613\u5bdf\u89c9\u7684\u95ee\u9898\uff0c\n\u56e0\u4e3a\u4e00\u4e2aproperty\u5176\u5b9e\u662f getter\u3001setter \u548c deleter \u65b9\u6cd5\u7684\u96c6\u5408\uff0c\u800c\u4e0d\u662f\u5355\u4e2a\u65b9\u6cd5\u3002\n\u56e0\u6b64\uff0c\u5f53\u4f60\u6269\u5c55\u4e00\u4e2aproperty\u7684\u65f6\u5019\uff0c\u4f60\u9700\u8981\u5148\u786e\u5b9a\u4f60\u662f\u5426\u8981\u91cd\u65b0\u5b9a\u4e49\u6240\u6709\u7684\u65b9\u6cd5\u8fd8\u662f\u8bf4\u53ea\u4fee\u6539\u5176\u4e2d\u67d0\u4e00\u4e2a\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5728\u7b2c\u4e00\u4e2a\u4f8b\u5b50\u4e2d\uff0c\u6240\u6709\u7684property\u65b9\u6cd5\u90fd\u88ab\u91cd\u65b0\u5b9a\u4e49\u3002\n\u5728\u6bcf\u4e00\u4e2a\u65b9\u6cd5\u4e2d\uff0c\u4f7f\u7528\u4e86 super() \u6765\u8c03\u7528\u7236\u7c7b\u7684\u5b9e\u73b0\u3002\n\u5728 setter \u51fd\u6570\u4e2d\u4f7f\u7528 super(SubPerson, SubPerson).name.__set__(self, value) \u7684\u8bed\u53e5\u662f\u6ca1\u6709\u9519\u7684\u3002\n\u4e3a\u4e86\u59d4\u6258\u7ed9\u4e4b\u524d\u5b9a\u4e49\u7684setter\u65b9\u6cd5\uff0c\u9700\u8981\u5c06\u63a7\u5236\u6743\u4f20\u9012\u7ed9\u4e4b\u524d\u5b9a\u4e49\u7684name\u5c5e\u6027\u7684 __set__() \u65b9\u6cd5\u3002\n\u4e0d\u8fc7\uff0c\u83b7\u53d6\u8fd9\u4e2a\u65b9\u6cd5\u7684\u552f\u4e00\u9014\u5f84\u662f\u4f7f\u7528\u7c7b\u53d8\u91cf\u800c\u4e0d\u662f\u5b9e\u4f8b\u53d8\u91cf\u6765\u8bbf\u95ee\u5b83\u3002\n\u8fd9\u4e5f\u662f\u4e3a\u4ec0\u4e48\u6211\u4eec\u8981\u4f7f\u7528 super(SubPerson, SubPerson) \u7684\u539f\u56e0\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u4f60\u53ea\u60f3\u91cd\u5b9a\u4e49\u5176\u4e2d\u4e00\u4e2a\u65b9\u6cd5\uff0c\u90a3\u53ea\u4f7f\u7528 @property \u672c\u8eab\u662f\u4e0d\u591f\u7684\u3002\u6bd4\u5982\uff0c\u4e0b\u9762\u7684\u4ee3\u7801\u5c31\u65e0\u6cd5\u5de5\u4f5c\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class SubPerson(Person):\n    @property  # Doesn't work\n    def name(self):\n        print('Getting name')\n        return super().name"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u4f60\u8bd5\u7740\u8fd0\u884c\u4f1a\u53d1\u73b0setter\u51fd\u6570\u6574\u4e2a\u6d88\u5931\u4e86\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "s = SubPerson('Guido')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u5e94\u8be5\u50cf\u4e4b\u524d\u8bf4\u8fc7\u7684\u90a3\u6837\u4fee\u6539\u4ee3\u7801\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class SubPerson(Person):\n    @Person.name.getter\n    def name(self):\n        print('Getting name')\n        return super().name"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u4e48\u5199\u540e\uff0cproperty\u4e4b\u524d\u5df2\u7ecf\u5b9a\u4e49\u8fc7\u7684\u65b9\u6cd5\u4f1a\u88ab\u590d\u5236\u8fc7\u6765\uff0c\u800cgetter\u51fd\u6570\u88ab\u66ff\u6362\u3002\u7136\u540e\u5b83\u5c31\u80fd\u6309\u7167\u671f\u671b\u7684\u5de5\u4f5c\u4e86\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "s = SubPerson('Guido')\ns.name"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "s.name = 'Larry'\ns.name"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "s.name = 42"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5728\u8fd9\u4e2a\u7279\u522b\u7684\u89e3\u51b3\u65b9\u6848\u4e2d\uff0c\u6211\u4eec\u6ca1\u529e\u6cd5\u4f7f\u7528\u66f4\u52a0\u901a\u7528\u7684\u65b9\u5f0f\u53bb\u66ff\u6362\u786c\u7f16\u7801\u7684 Person \u7c7b\u540d\u3002\n\u5982\u679c\u4f60\u4e0d\u77e5\u9053\u5230\u5e95\u662f\u54ea\u4e2a\u57fa\u7c7b\u5b9a\u4e49\u4e86property\uff0c\n\u90a3\u4f60\u53ea\u80fd\u901a\u8fc7\u91cd\u65b0\u5b9a\u4e49\u6240\u6709property\u5e76\u4f7f\u7528 super() \u6765\u5c06\u63a7\u5236\u6743\u4f20\u9012\u7ed9\u524d\u9762\u7684\u5b9e\u73b0\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u503c\u5f97\u6ce8\u610f\u7684\u662f\u4e0a\u9762\u6f14\u793a\u7684\u7b2c\u4e00\u79cd\u6280\u672f\u8fd8\u53ef\u4ee5\u88ab\u7528\u6765\u6269\u5c55\u4e00\u4e2a\u63cf\u8ff0\u5668(\u57288.9\u5c0f\u8282\u6211\u4eec\u6709\u4e13\u95e8\u7684\u4ecb\u7ecd)\u3002\u6bd4\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# A descriptor\nclass String:\n    def __init__(self, name):\n        self.name = name\n\n    def __get__(self, instance, cls):\n        if instance is None:\n            return self\n        return instance.__dict__[self.name]\n\n    def __set__(self, instance, value):\n        if not isinstance(value, str):\n            raise TypeError('Expected a string')\n        instance.__dict__[self.name] = value\n\n# A class with a descriptor\nclass Person:\n    name = String('name')\n\n    def __init__(self, name):\n        self.name = name\n\n# Extending a descriptor with a property\nclass SubPerson(Person):\n    @property\n    def name(self):\n        print('Getting name')\n        return super().name\n\n    @name.setter\n    def name(self, value):\n        print('Setting name to', value)\n        super(SubPerson, SubPerson).name.__set__(self, value)\n\n    @name.deleter\n    def name(self):\n        print('Deleting name')\n        super(SubPerson, SubPerson).name.__delete__(self)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u6700\u540e\u503c\u5f97\u6ce8\u610f\u7684\u662f\uff0c\u8bfb\u5230\u8fd9\u91cc\u65f6\uff0c\u4f60\u5e94\u8be5\u4f1a\u53d1\u73b0\u5b50\u7c7b\u5316 setter \u548c deleter \u65b9\u6cd5\u5176\u5b9e\u662f\u5f88\u7b80\u5355\u7684\u3002\n\u8fd9\u91cc\u6f14\u793a\u7684\u89e3\u51b3\u65b9\u6848\u540c\u6837\u9002\u7528\uff0c\u4f46\u662f\u5728 Python\u7684issue\u9875\u9762\n\u62a5\u544a\u7684\u4e00\u4e2abug\uff0c\u6216\u8bb8\u4f1a\u4f7f\u5f97\u5c06\u6765\u7684Python\u7248\u672c\u4e2d\u51fa\u73b0\u4e00\u4e2a\u66f4\u52a0\u7b80\u6d01\u7684\u65b9\u6cd5\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 8.9 \u521b\u5efa\u65b0\u7684\u7c7b\u6216\u5b9e\u4f8b\u5c5e\u6027\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u60f3\u521b\u5efa\u4e00\u4e2a\u65b0\u7684\u62e5\u6709\u4e00\u4e9b\u989d\u5916\u529f\u80fd\u7684\u5b9e\u4f8b\u5c5e\u6027\u7c7b\u578b\uff0c\u6bd4\u5982\u7c7b\u578b\u68c0\u67e5\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u4f60\u60f3\u521b\u5efa\u4e00\u4e2a\u5168\u65b0\u7684\u5b9e\u4f8b\u5c5e\u6027\uff0c\u53ef\u4ee5\u901a\u8fc7\u4e00\u4e2a\u63cf\u8ff0\u5668\u7c7b\u7684\u5f62\u5f0f\u6765\u5b9a\u4e49\u5b83\u7684\u529f\u80fd\u3002\u4e0b\u9762\u662f\u4e00\u4e2a\u4f8b\u5b50\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# Descriptor attribute for an integer type-checked attribute\nclass Integer:\n    def __init__(self, name):\n        self.name = name\n\n    def __get__(self, instance, cls):\n        if instance is None:\n            return self\n        else:\n            return instance.__dict__[self.name]\n\n    def __set__(self, instance, value):\n        if not isinstance(value, int):\n            raise TypeError('Expected an int')\n        instance.__dict__[self.name] = value\n\n    def __delete__(self, instance):\n        del instance.__dict__[self.name]"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e00\u4e2a\u63cf\u8ff0\u5668\u5c31\u662f\u4e00\u4e2a\u5b9e\u73b0\u4e86\u4e09\u4e2a\u6838\u5fc3\u7684\u5c5e\u6027\u8bbf\u95ee\u64cd\u4f5c(get, set, delete)\u7684\u7c7b\uff0c\n\u5206\u522b\u4e3a __get__() \u3001__set__() \u548c __delete__() \u8fd9\u4e09\u4e2a\u7279\u6b8a\u7684\u65b9\u6cd5\u3002\n\u8fd9\u4e9b\u65b9\u6cd5\u63a5\u53d7\u4e00\u4e2a\u5b9e\u4f8b\u4f5c\u4e3a\u8f93\u5165\uff0c\u4e4b\u540e\u76f8\u5e94\u7684\u64cd\u4f5c\u5b9e\u4f8b\u5e95\u5c42\u7684\u5b57\u5178\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e3a\u4e86\u4f7f\u7528\u4e00\u4e2a\u63cf\u8ff0\u5668\uff0c\u9700\u5c06\u8fd9\u4e2a\u63cf\u8ff0\u5668\u7684\u5b9e\u4f8b\u4f5c\u4e3a\u7c7b\u5c5e\u6027\u653e\u5230\u4e00\u4e2a\u7c7b\u7684\u5b9a\u4e49\u4e2d\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class Point:\n    x = Integer('x')\n    y = Integer('y')\n\n    def __init__(self, x, y):\n        self.x = x\n        self.y = y"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5f53\u4f60\u8fd9\u6837\u505a\u540e\uff0c\u6240\u6709\u5bf9\u63cf\u8ff0\u5668\u5c5e\u6027(\u6bd4\u5982x\u6216y)\u7684\u8bbf\u95ee\u4f1a\u88ab\n__get__() \u3001__set__() \u548c __delete__() \u65b9\u6cd5\u6355\u83b7\u5230\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "p = Point(2, 3)\np.x # Calls Point.x.__get__(p,Point)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "p.y = 5 # Calls Point.y.__set__(p, 5)\np.x = 2.3 # Calls Point.x.__set__(p, 2.3)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f5c\u4e3a\u8f93\u5165\uff0c\u63cf\u8ff0\u5668\u7684\u6bcf\u4e00\u4e2a\u65b9\u6cd5\u4f1a\u63a5\u53d7\u4e00\u4e2a\u64cd\u4f5c\u5b9e\u4f8b\u3002\n\u4e3a\u4e86\u5b9e\u73b0\u8bf7\u6c42\u64cd\u4f5c\uff0c\u4f1a\u76f8\u5e94\u7684\u64cd\u4f5c\u5b9e\u4f8b\u5e95\u5c42\u7684\u5b57\u5178(__dict__\u5c5e\u6027)\u3002\n\u63cf\u8ff0\u5668\u7684 self.name \u5c5e\u6027\u5b58\u50a8\u4e86\u5728\u5b9e\u4f8b\u5b57\u5178\u4e2d\u88ab\u5b9e\u9645\u4f7f\u7528\u5230\u7684key\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u63cf\u8ff0\u5668\u53ef\u5b9e\u73b0\u5927\u90e8\u5206Python\u7c7b\u7279\u6027\u4e2d\u7684\u5e95\u5c42\u9b54\u6cd5\uff0c\n\u5305\u62ec @classmethod \u3001@staticmethod \u3001@property \uff0c\u751a\u81f3\u662f __slots__ \u7279\u6027\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u901a\u8fc7\u5b9a\u4e49\u4e00\u4e2a\u63cf\u8ff0\u5668\uff0c\u4f60\u53ef\u4ee5\u5728\u5e95\u5c42\u6355\u83b7\u6838\u5fc3\u7684\u5b9e\u4f8b\u64cd\u4f5c(get, set, delete)\uff0c\u5e76\u4e14\u53ef\u5b8c\u5168\u81ea\u5b9a\u4e49\u5b83\u4eec\u7684\u884c\u4e3a\u3002\n\u8fd9\u662f\u4e00\u4e2a\u5f3a\u5927\u7684\u5de5\u5177\uff0c\u6709\u4e86\u5b83\u4f60\u53ef\u4ee5\u5b9e\u73b0\u5f88\u591a\u9ad8\u7ea7\u529f\u80fd\uff0c\u5e76\u4e14\u5b83\u4e5f\u662f\u5f88\u591a\u9ad8\u7ea7\u5e93\u548c\u6846\u67b6\u4e2d\u7684\u91cd\u8981\u5de5\u5177\u4e4b\u4e00\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u63cf\u8ff0\u5668\u7684\u4e00\u4e2a\u6bd4\u8f83\u56f0\u60d1\u7684\u5730\u65b9\u662f\u5b83\u53ea\u80fd\u5728\u7c7b\u7ea7\u522b\u88ab\u5b9a\u4e49\uff0c\u800c\u4e0d\u80fd\u4e3a\u6bcf\u4e2a\u5b9e\u4f8b\u5355\u72ec\u5b9a\u4e49\u3002\u56e0\u6b64\uff0c\u4e0b\u9762\u7684\u4ee3\u7801\u662f\u65e0\u6cd5\u5de5\u4f5c\u7684\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# Does NOT work\nclass Point:\n    def __init__(self, x, y):\n        self.x = Integer('x') # No! Must be a class variable\n        self.y = Integer('y')\n        self.x = x\n        self.y = y"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u540c\u65f6\uff0c__get__() \u65b9\u6cd5\u5b9e\u73b0\u8d77\u6765\u6bd4\u770b\u4e0a\u53bb\u8981\u590d\u6742\u5f97\u591a\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# Descriptor attribute for an integer type-checked attribute\nclass Integer:\n\n    def __get__(self, instance, cls):\n        if instance is None:\n            return self\n        else:\n            return instance.__dict__[self.name]"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "__get__() \u770b\u4e0a\u53bb\u6709\u70b9\u590d\u6742\u7684\u539f\u56e0\u5f52\u7ed3\u4e8e\u5b9e\u4f8b\u53d8\u91cf\u548c\u7c7b\u53d8\u91cf\u7684\u4e0d\u540c\u3002\n\u5982\u679c\u4e00\u4e2a\u63cf\u8ff0\u5668\u88ab\u5f53\u505a\u4e00\u4e2a\u7c7b\u53d8\u91cf\u6765\u8bbf\u95ee\uff0c\u90a3\u4e48 instance \u53c2\u6570\u88ab\u8bbe\u7f6e\u6210 None \u3002\n\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u6807\u51c6\u505a\u6cd5\u5c31\u662f\u7b80\u5355\u7684\u8fd4\u56de\u8fd9\u4e2a\u63cf\u8ff0\u5668\u672c\u8eab\u5373\u53ef(\u5c3d\u7ba1\u4f60\u8fd8\u53ef\u4ee5\u6dfb\u52a0\u5176\u4ed6\u7684\u81ea\u5b9a\u4e49\u64cd\u4f5c)\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "p = Point(2,3)\np.x # Calls Point.x.__get__(p, Point)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "Point.x # Calls Point.x.__get__(None, Point)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u63cf\u8ff0\u5668\u901a\u5e38\u662f\u90a3\u4e9b\u4f7f\u7528\u5230\u88c5\u9970\u5668\u6216\u5143\u7c7b\u7684\u5927\u578b\u6846\u67b6\u4e2d\u7684\u4e00\u4e2a\u7ec4\u4ef6\u3002\u540c\u65f6\u5b83\u4eec\u7684\u4f7f\u7528\u4e5f\u88ab\u9690\u85cf\u5728\u540e\u9762\u3002\n\u4e3e\u4e2a\u4f8b\u5b50\uff0c\u4e0b\u9762\u662f\u4e00\u4e9b\u66f4\u9ad8\u7ea7\u7684\u57fa\u4e8e\u63cf\u8ff0\u5668\u7684\u4ee3\u7801\uff0c\u5e76\u6d89\u53ca\u5230\u4e00\u4e2a\u7c7b\u88c5\u9970\u5668\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# Descriptor for a type-checked attribute\nclass Typed:\n    def __init__(self, name, expected_type):\n        self.name = name\n        self.expected_type = expected_type\n    def __get__(self, instance, cls):\n        if instance is None:\n            return self\n        else:\n            return instance.__dict__[self.name]\n\n    def __set__(self, instance, value):\n        if not isinstance(value, self.expected_type):\n            raise TypeError('Expected ' + str(self.expected_type))\n        instance.__dict__[self.name] = value\n    def __delete__(self, instance):\n        del instance.__dict__[self.name]\n\n# Class decorator that applies it to selected attributes\ndef typeassert(**kwargs):\n    def decorate(cls):\n        for name, expected_type in kwargs.items():\n            # Attach a Typed descriptor to the class\n            setattr(cls, name, Typed(name, expected_type))\n        return cls\n    return decorate\n\n# Example use\n@typeassert(name=str, shares=int, price=float)\nclass Stock:\n    def __init__(self, name, shares, price):\n        self.name = name\n        self.shares = shares\n        self.price = price"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u6700\u540e\u8981\u6307\u51fa\u7684\u4e00\u70b9\u662f\uff0c\u5982\u679c\u4f60\u53ea\u662f\u60f3\u7b80\u5355\u7684\u81ea\u5b9a\u4e49\u67d0\u4e2a\u7c7b\u7684\u5355\u4e2a\u5c5e\u6027\u8bbf\u95ee\u7684\u8bdd\u5c31\u4e0d\u7528\u53bb\u5199\u63cf\u8ff0\u5668\u4e86\u3002\n\u8fd9\u79cd\u60c5\u51b5\u4e0b\u4f7f\u75288.6\u5c0f\u8282\u4ecb\u7ecd\u7684property\u6280\u672f\u4f1a\u66f4\u52a0\u5bb9\u6613\u3002\n\u5f53\u7a0b\u5e8f\u4e2d\u6709\u5f88\u591a\u91cd\u590d\u4ee3\u7801\u7684\u65f6\u5019\u63cf\u8ff0\u5668\u5c31\u5f88\u6709\u7528\u4e86\n(\u6bd4\u5982\u4f60\u60f3\u5728\u4f60\u4ee3\u7801\u7684\u5f88\u591a\u5730\u65b9\u4f7f\u7528\u63cf\u8ff0\u5668\u63d0\u4f9b\u7684\u529f\u80fd\u6216\u8005\u5c06\u5b83\u4f5c\u4e3a\u4e00\u4e2a\u51fd\u6570\u5e93\u7279\u6027)\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 8.10 \u4f7f\u7528\u5ef6\u8fdf\u8ba1\u7b97\u5c5e\u6027\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u60f3\u5c06\u4e00\u4e2a\u53ea\u8bfb\u5c5e\u6027\u5b9a\u4e49\u6210\u4e00\u4e2aproperty\uff0c\u5e76\u4e14\u53ea\u5728\u8bbf\u95ee\u7684\u65f6\u5019\u624d\u4f1a\u8ba1\u7b97\u7ed3\u679c\u3002\n\u4f46\u662f\u4e00\u65e6\u88ab\u8bbf\u95ee\u540e\uff0c\u4f60\u5e0c\u671b\u7ed3\u679c\u503c\u88ab\u7f13\u5b58\u8d77\u6765\uff0c\u4e0d\u7528\u6bcf\u6b21\u90fd\u53bb\u8ba1\u7b97\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5b9a\u4e49\u4e00\u4e2a\u5ef6\u8fdf\u5c5e\u6027\u7684\u4e00\u79cd\u9ad8\u6548\u65b9\u6cd5\u662f\u901a\u8fc7\u4f7f\u7528\u4e00\u4e2a\u63cf\u8ff0\u5668\u7c7b\uff0c\u5982\u4e0b\u6240\u793a\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class lazyproperty:\n    def __init__(self, func):\n        self.func = func\n\n    def __get__(self, instance, cls):\n        if instance is None:\n            return self\n        else:\n            value = self.func(instance)\n            setattr(instance, self.func.__name__, value)\n            return value"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u9700\u8981\u50cf\u4e0b\u9762\u8fd9\u6837\u5728\u4e00\u4e2a\u7c7b\u4e2d\u4f7f\u7528\u5b83\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import math\n\nclass Circle:\n    def __init__(self, radius):\n        self.radius = radius\n\n    @lazyproperty\n    def area(self):\n        print('Computing area')\n        return math.pi * self.radius ** 2\n\n    @lazyproperty\n    def perimeter(self):\n        print('Computing perimeter')\n        return 2 * math.pi * self.radius"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e0b\u9762\u5728\u4e00\u4e2a\u4ea4\u4e92\u73af\u5883\u4e2d\u6f14\u793a\u5b83\u7684\u4f7f\u7528\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "c = Circle(4.0)\nc.radius"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "c.area"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "c.area"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "c.perimeter"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "c.perimeter"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4ed4\u7ec6\u89c2\u5bdf\u4f60\u4f1a\u53d1\u73b0\u6d88\u606f Computing area \u548c Computing perimeter \u4ec5\u4ec5\u51fa\u73b0\u4e00\u6b21\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5f88\u591a\u65f6\u5019\uff0c\u6784\u9020\u4e00\u4e2a\u5ef6\u8fdf\u8ba1\u7b97\u5c5e\u6027\u7684\u4e3b\u8981\u76ee\u7684\u662f\u4e3a\u4e86\u63d0\u5347\u6027\u80fd\u3002\n\u4f8b\u5982\uff0c\u4f60\u53ef\u4ee5\u907f\u514d\u8ba1\u7b97\u8fd9\u4e9b\u5c5e\u6027\u503c\uff0c\u9664\u975e\u4f60\u771f\u7684\u9700\u8981\u5b83\u4eec\u3002\n\u8fd9\u91cc\u6f14\u793a\u7684\u65b9\u6848\u5c31\u662f\u7528\u6765\u5b9e\u73b0\u8fd9\u6837\u7684\u6548\u679c\u7684\uff0c\n\u53ea\u4e0d\u8fc7\u5b83\u662f\u901a\u8fc7\u4ee5\u975e\u5e38\u9ad8\u6548\u7684\u65b9\u5f0f\u4f7f\u7528\u63cf\u8ff0\u5668\u7684\u4e00\u4e2a\u7cbe\u5999\u7279\u6027\u6765\u8fbe\u5230\u8fd9\u79cd\u6548\u679c\u7684\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u6b63\u5982\u5728\u5176\u4ed6\u5c0f\u8282(\u59828.9\u5c0f\u8282)\u6240\u8bb2\u7684\u90a3\u6837\uff0c\u5f53\u4e00\u4e2a\u63cf\u8ff0\u5668\u88ab\u653e\u5165\u4e00\u4e2a\u7c7b\u7684\u5b9a\u4e49\u65f6\uff0c\n\u6bcf\u6b21\u8bbf\u95ee\u5c5e\u6027\u65f6\u5b83\u7684 __get__() \u3001__set__() \u548c __delete__() \u65b9\u6cd5\u5c31\u4f1a\u88ab\u89e6\u53d1\u3002\n\u4e0d\u8fc7\uff0c\u5982\u679c\u4e00\u4e2a\u63cf\u8ff0\u5668\u4ec5\u4ec5\u53ea\u5b9a\u4e49\u4e86\u4e00\u4e2a __get__() \u65b9\u6cd5\u7684\u8bdd\uff0c\u5b83\u6bd4\u901a\u5e38\u7684\u5177\u6709\u66f4\u5f31\u7684\u7ed1\u5b9a\u3002\n\u7279\u522b\u5730\uff0c\u53ea\u6709\u5f53\u88ab\u8bbf\u95ee\u5c5e\u6027\u4e0d\u5728\u5b9e\u4f8b\u5e95\u5c42\u7684\u5b57\u5178\u4e2d\u65f6 __get__() \u65b9\u6cd5\u624d\u4f1a\u88ab\u89e6\u53d1\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "lazyproperty \u7c7b\u5229\u7528\u8fd9\u4e00\u70b9\uff0c\u4f7f\u7528 __get__() \u65b9\u6cd5\u5728\u5b9e\u4f8b\u4e2d\u5b58\u50a8\u8ba1\u7b97\u51fa\u6765\u7684\u503c\uff0c\n\u8fd9\u4e2a\u5b9e\u4f8b\u4f7f\u7528\u76f8\u540c\u7684\u540d\u5b57\u4f5c\u4e3a\u5b83\u7684property\u3002\n\u8fd9\u6837\u4e00\u6765\uff0c\u7ed3\u679c\u503c\u88ab\u5b58\u50a8\u5728\u5b9e\u4f8b\u5b57\u5178\u4e2d\u5e76\u4e14\u4ee5\u540e\u5c31\u4e0d\u9700\u8981\u518d\u53bb\u8ba1\u7b97\u8fd9\u4e2aproperty\u4e86\u3002\n\u4f60\u53ef\u4ee5\u5c1d\u8bd5\u66f4\u6df1\u5165\u7684\u4f8b\u5b50\u6765\u89c2\u5bdf\u7ed3\u679c\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "c = Circle(4.0)\n# Get instance variables\nvars(c)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# Compute area and observe variables afterward\nc.area"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "vars(c)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# Notice access doesn't invoke property anymore\nc.area"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# Delete the variable and see property trigger again\ndel c.area\nvars(c)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "c.area"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u79cd\u65b9\u6848\u6709\u4e00\u4e2a\u5c0f\u7f3a\u9677\u5c31\u662f\u8ba1\u7b97\u51fa\u7684\u503c\u88ab\u521b\u5efa\u540e\u662f\u53ef\u4ee5\u88ab\u4fee\u6539\u7684\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "c.area"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "c.area = 25\nc.area"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u4f60\u62c5\u5fc3\u8fd9\u4e2a\u95ee\u9898\uff0c\u90a3\u4e48\u53ef\u4ee5\u4f7f\u7528\u4e00\u79cd\u7a0d\u5fae\u6ca1\u90a3\u4e48\u9ad8\u6548\u7684\u5b9e\u73b0\uff0c\u5c31\u50cf\u4e0b\u9762\u8fd9\u6837\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "def lazyproperty(func):\n    name = '_lazy_' + func.__name__\n    @property\n    def lazy(self):\n        if hasattr(self, name):\n            return getattr(self, name)\n        else:\n            value = func(self)\n            setattr(self, name, value)\n            return value\n    return lazy"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u4f60\u4f7f\u7528\u8fd9\u4e2a\u7248\u672c\uff0c\u5c31\u4f1a\u53d1\u73b0\u73b0\u5728\u4fee\u6539\u64cd\u4f5c\u5df2\u7ecf\u4e0d\u88ab\u5141\u8bb8\u4e86\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "c = Circle(4.0)\nc.area"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "c.area"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "c.area = 25"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u7136\u800c\uff0c\u8fd9\u79cd\u65b9\u6848\u6709\u4e00\u4e2a\u7f3a\u70b9\u5c31\u662f\u6240\u6709get\u64cd\u4f5c\u90fd\u5fc5\u987b\u88ab\u5b9a\u5411\u5230\u5c5e\u6027\u7684 getter \u51fd\u6570\u4e0a\u53bb\u3002\n\u8fd9\u4e2a\u8ddf\u4e4b\u524d\u7b80\u5355\u7684\u5728\u5b9e\u4f8b\u5b57\u5178\u4e2d\u67e5\u627e\u503c\u7684\u65b9\u6848\u76f8\u6bd4\u6548\u7387\u8981\u4f4e\u4e00\u70b9\u3002\n\u5982\u679c\u60f3\u83b7\u53d6\u66f4\u591a\u5173\u4e8eproperty\u548c\u53ef\u7ba1\u7406\u5c5e\u6027\u7684\u4fe1\u606f\uff0c\u53ef\u4ee5\u53c2\u80038.6\u5c0f\u8282\u3002\u800c\u63cf\u8ff0\u5668\u7684\u76f8\u5173\u5185\u5bb9\u53ef\u4ee5\u57288.9\u5c0f\u8282\u627e\u5230\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 8.11 \u7b80\u5316\u6570\u636e\u7ed3\u6784\u7684\u521d\u59cb\u5316\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u5199\u4e86\u5f88\u591a\u4ec5\u4ec5\u7528\u4f5c\u6570\u636e\u7ed3\u6784\u7684\u7c7b\uff0c\u4e0d\u60f3\u5199\u592a\u591a\u70e6\u4eba\u7684 __init__() \u51fd\u6570"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u53ef\u4ee5\u5728\u4e00\u4e2a\u57fa\u7c7b\u4e2d\u5199\u4e00\u4e2a\u516c\u7528\u7684 __init__() \u51fd\u6570\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import math\n\nclass Structure1:\n    # Class variable that specifies expected fields\n    _fields = []\n\n    def __init__(self, *args):\n        if len(args) != len(self._fields):\n            raise TypeError('Expected {} arguments'.format(len(self._fields)))\n        # Set the arguments\n        for name, value in zip(self._fields, args):\n            setattr(self, name, value)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u7136\u540e\u4f7f\u4f60\u7684\u7c7b\u7ee7\u627f\u81ea\u8fd9\u4e2a\u57fa\u7c7b:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# Example class definitions\nclass Stock(Structure1):\n    _fields = ['name', 'shares', 'price']\n\nclass Point(Structure1):\n    _fields = ['x', 'y']\n\nclass Circle(Structure1):\n    _fields = ['radius']\n\n    def area(self):\n        return math.pi * self.radius ** 2"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f7f\u7528\u8fd9\u4e9b\u7c7b\u7684\u793a\u4f8b\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "s = Stock('ACME', 50, 91.1)\np = Point(2, 3)\nc = Circle(4.5)\ns2 = Stock('ACME', 50)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u8fd8\u60f3\u652f\u6301\u5173\u952e\u5b57\u53c2\u6570\uff0c\u53ef\u4ee5\u5c06\u5173\u952e\u5b57\u53c2\u6570\u8bbe\u7f6e\u4e3a\u5b9e\u4f8b\u5c5e\u6027\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class Structure2:\n    _fields = []\n\n    def __init__(self, *args, **kwargs):\n        if len(args) > len(self._fields):\n            raise TypeError('Expected {} arguments'.format(len(self._fields)))\n\n        # Set all of the positional arguments\n        for name, value in zip(self._fields, args):\n            setattr(self, name, value)\n\n        # Set the remaining keyword arguments\n        for name in self._fields[len(args):]:\n            setattr(self, name, kwargs.pop(name))\n\n        # Check for any remaining unknown arguments\n        if kwargs:\n            raise TypeError('Invalid argument(s): {}'.format(','.join(kwargs)))\n# Example use\nif __name__ == '__main__':\n    class Stock(Structure2):\n        _fields = ['name', 'shares', 'price']\n\n    s1 = Stock('ACME', 50, 91.1)\n    s2 = Stock('ACME', 50, price=91.1)\n    s3 = Stock('ACME', shares=50, price=91.1)\n    # s3 = Stock('ACME', shares=50, price=91.1, aa=1)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u8fd8\u80fd\u5c06\u4e0d\u5728 _fields \u4e2d\u7684\u540d\u79f0\u52a0\u5165\u5230\u5c5e\u6027\u4e2d\u53bb\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class Structure3:\n    # Class variable that specifies expected fields\n    _fields = []\n\n    def __init__(self, *args, **kwargs):\n        if len(args) != len(self._fields):\n            raise TypeError('Expected {} arguments'.format(len(self._fields)))\n\n        # Set the arguments\n        for name, value in zip(self._fields, args):\n            setattr(self, name, value)\n\n        # Set the additional arguments (if any)\n        extra_args = kwargs.keys() - self._fields\n        for name in extra_args:\n            setattr(self, name, kwargs.pop(name))\n\n        if kwargs:\n            raise TypeError('Duplicate values for {}'.format(','.join(kwargs)))\n\n# Example use\nif __name__ == '__main__':\n    class Stock(Structure3):\n        _fields = ['name', 'shares', 'price']\n\n    s1 = Stock('ACME', 50, 91.1)\n    s2 = Stock('ACME', 50, 91.1, date='8/2/2012')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5f53\u4f60\u9700\u8981\u4f7f\u7528\u5927\u91cf\u5f88\u5c0f\u7684\u6570\u636e\u7ed3\u6784\u7c7b\u7684\u65f6\u5019\uff0c\n\u76f8\u6bd4\u624b\u5de5\u4e00\u4e2a\u4e2a\u5b9a\u4e49 __init__() \u65b9\u6cd5\u800c\u5df2\uff0c\u4f7f\u7528\u8fd9\u79cd\u65b9\u5f0f\u53ef\u4ee5\u5927\u5927\u7b80\u5316\u4ee3\u7801\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5728\u4e0a\u9762\u7684\u5b9e\u73b0\u4e2d\u6211\u4eec\u4f7f\u7528\u4e86 setattr() \u51fd\u6570\u7c7b\u8bbe\u7f6e\u5c5e\u6027\u503c\uff0c\n\u4f60\u53ef\u80fd\u4e0d\u60f3\u7528\u8fd9\u79cd\u65b9\u5f0f\uff0c\u800c\u662f\u60f3\u76f4\u63a5\u66f4\u65b0\u5b9e\u4f8b\u5b57\u5178\uff0c\u5c31\u50cf\u4e0b\u9762\u8fd9\u6837\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class Structure:\n    # Class variable that specifies expected fields\n    _fields= []\n    def __init__(self, *args):\n        if len(args) != len(self._fields):\n            raise TypeError('Expected {} arguments'.format(len(self._fields)))\n\n        # Set the arguments (alternate)\n        self.__dict__.update(zip(self._fields,args))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5c3d\u7ba1\u8fd9\u4e5f\u53ef\u4ee5\u6b63\u5e38\u5de5\u4f5c\uff0c\u4f46\u662f\u5f53\u5b9a\u4e49\u5b50\u7c7b\u7684\u65f6\u5019\u95ee\u9898\u5c31\u6765\u4e86\u3002\n\u5f53\u4e00\u4e2a\u5b50\u7c7b\u5b9a\u4e49\u4e86 __slots__ \u6216\u8005\u901a\u8fc7property(\u6216\u63cf\u8ff0\u5668)\u6765\u5305\u88c5\u67d0\u4e2a\u5c5e\u6027\uff0c\n\u90a3\u4e48\u76f4\u63a5\u8bbf\u95ee\u5b9e\u4f8b\u5b57\u5178\u5c31\u4e0d\u8d77\u4f5c\u7528\u4e86\u3002\u6211\u4eec\u4e0a\u9762\u4f7f\u7528 setattr() \u4f1a\u663e\u5f97\u66f4\u901a\u7528\u4e9b\uff0c\u56e0\u4e3a\u5b83\u4e5f\u9002\u7528\u4e8e\u5b50\u7c7b\u60c5\u51b5\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u79cd\u65b9\u6cd5\u552f\u4e00\u4e0d\u597d\u7684\u5730\u65b9\u5c31\u662f\u5bf9\u67d0\u4e9bIDE\u800c\u8a00\uff0c\u5728\u663e\u793a\u5e2e\u52a9\u51fd\u6570\u65f6\u53ef\u80fd\u4e0d\u592a\u53cb\u597d\u3002\u6bd4\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "help(Stock)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u53ef\u4ee5\u53c2\u80039.16\u5c0f\u8282\u6765\u5f3a\u5236\u5728 __init__() \u65b9\u6cd5\u4e2d\u6307\u5b9a\u53c2\u6570\u7684\u7c7b\u578b\u7b7e\u540d\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 8.12 \u5b9a\u4e49\u63a5\u53e3\u6216\u8005\u62bd\u8c61\u57fa\u7c7b\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u60f3\u5b9a\u4e49\u4e00\u4e2a\u63a5\u53e3\u6216\u62bd\u8c61\u7c7b\uff0c\u5e76\u4e14\u901a\u8fc7\u6267\u884c\u7c7b\u578b\u68c0\u67e5\u6765\u786e\u4fdd\u5b50\u7c7b\u5b9e\u73b0\u4e86\u67d0\u4e9b\u7279\u5b9a\u7684\u65b9\u6cd5"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f7f\u7528 abc \u6a21\u5757\u53ef\u4ee5\u5f88\u8f7b\u677e\u7684\u5b9a\u4e49\u62bd\u8c61\u57fa\u7c7b\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "from abc import ABCMeta, abstractmethod\n\nclass IStream(metaclass=ABCMeta):\n    @abstractmethod\n    def read(self, maxbytes=-1):\n        pass\n\n    @abstractmethod\n    def write(self, data):\n        pass"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u62bd\u8c61\u7c7b\u7684\u4e00\u4e2a\u7279\u70b9\u662f\u5b83\u4e0d\u80fd\u76f4\u63a5\u88ab\u5b9e\u4f8b\u5316\uff0c\u6bd4\u5982\u4f60\u60f3\u50cf\u4e0b\u9762\u8fd9\u6837\u505a\u662f\u4e0d\u884c\u7684\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "a = IStream() # TypeError: Can't instantiate abstract class\n                # IStream with abstract methods read, write"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u62bd\u8c61\u7c7b\u7684\u76ee\u7684\u5c31\u662f\u8ba9\u522b\u7684\u7c7b\u7ee7\u627f\u5b83\u5e76\u5b9e\u73b0\u7279\u5b9a\u7684\u62bd\u8c61\u65b9\u6cd5\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class SocketStream(IStream):\n    def read(self, maxbytes=-1):\n        pass\n\n    def write(self, data):\n        pass"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u62bd\u8c61\u57fa\u7c7b\u7684\u4e00\u4e2a\u4e3b\u8981\u7528\u9014\u662f\u5728\u4ee3\u7801\u4e2d\u68c0\u67e5\u67d0\u4e9b\u7c7b\u662f\u5426\u4e3a\u7279\u5b9a\u7c7b\u578b\uff0c\u5b9e\u73b0\u4e86\u7279\u5b9a\u63a5\u53e3\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "def serialize(obj, stream):\n    if not isinstance(stream, IStream):\n        raise TypeError('Expected an IStream')\n    pass"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u9664\u4e86\u7ee7\u627f\u8fd9\u79cd\u65b9\u5f0f\u5916\uff0c\u8fd8\u53ef\u4ee5\u901a\u8fc7\u6ce8\u518c\u65b9\u5f0f\u6765\u8ba9\u67d0\u4e2a\u7c7b\u5b9e\u73b0\u62bd\u8c61\u57fa\u7c7b\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import io\n\n# Register the built-in I/O classes as supporting our interface\nIStream.register(io.IOBase)\n\n# Open a normal file and type check\nf = open('foo.txt')\nisinstance(f, IStream) # Returns True"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "@abstractmethod \u8fd8\u80fd\u6ce8\u89e3\u9759\u6001\u65b9\u6cd5\u3001\u7c7b\u65b9\u6cd5\u548c properties \u3002\n\u4f60\u53ea\u9700\u4fdd\u8bc1\u8fd9\u4e2a\u6ce8\u89e3\u7d27\u9760\u5728\u51fd\u6570\u5b9a\u4e49\u524d\u5373\u53ef\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class A(metaclass=ABCMeta):\n    @property\n    @abstractmethod\n    def name(self):\n        pass\n\n    @name.setter\n    @abstractmethod\n    def name(self, value):\n        pass\n\n    @classmethod\n    @abstractmethod\n    def method1(cls):\n        pass\n\n    @staticmethod\n    @abstractmethod\n    def method2():\n        pass"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u6807\u51c6\u5e93\u4e2d\u6709\u5f88\u591a\u7528\u5230\u62bd\u8c61\u57fa\u7c7b\u7684\u5730\u65b9\u3002collections \u6a21\u5757\u5b9a\u4e49\u4e86\u5f88\u591a\u8ddf\u5bb9\u5668\u548c\u8fed\u4ee3\u5668(\u5e8f\u5217\u3001\u6620\u5c04\u3001\u96c6\u5408\u7b49)\u6709\u5173\u7684\u62bd\u8c61\u57fa\u7c7b\u3002\nnumbers \u5e93\u5b9a\u4e49\u4e86\u8ddf\u6570\u5b57\u5bf9\u8c61(\u6574\u6570\u3001\u6d6e\u70b9\u6570\u3001\u6709\u7406\u6570\u7b49)\u6709\u5173\u7684\u57fa\u7c7b\u3002io \u5e93\u5b9a\u4e49\u4e86\u5f88\u591a\u8ddfI/O\u64cd\u4f5c\u76f8\u5173\u7684\u57fa\u7c7b\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u53ef\u4ee5\u4f7f\u7528\u9884\u5b9a\u4e49\u7684\u62bd\u8c61\u7c7b\u6765\u6267\u884c\u66f4\u901a\u7528\u7684\u7c7b\u578b\u68c0\u67e5\uff0c\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import collections\n\n# Check if x is a sequence\nif isinstance(x, collections.Sequence):\n...\n\n# Check if x is iterable\nif isinstance(x, collections.Iterable):\n...\n\n# Check if x has a size\nif isinstance(x, collections.Sized):\n...\n\n# Check if x is a mapping\nif isinstance(x, collections.Mapping):"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5c3d\u7ba1ABCs\u53ef\u4ee5\u8ba9\u6211\u4eec\u5f88\u65b9\u4fbf\u7684\u505a\u7c7b\u578b\u68c0\u67e5\uff0c\u4f46\u662f\u6211\u4eec\u5728\u4ee3\u7801\u4e2d\u6700\u597d\u4e0d\u8981\u8fc7\u591a\u7684\u4f7f\u7528\u5b83\u3002\n\u56e0\u4e3aPython\u7684\u672c\u8d28\u662f\u4e00\u95e8\u52a8\u6001\u7f16\u7a0b\u8bed\u8a00\uff0c\u5176\u76ee\u7684\u5c31\u662f\u7ed9\u4f60\u66f4\u591a\u7075\u6d3b\u6027\uff0c\n\u5f3a\u5236\u7c7b\u578b\u68c0\u67e5\u6216\u8ba9\u4f60\u4ee3\u7801\u53d8\u5f97\u66f4\u590d\u6742\uff0c\u8fd9\u6837\u505a\u65e0\u5f02\u4e8e\u820d\u672c\u6c42\u672b\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 8.13 \u5b9e\u73b0\u6570\u636e\u6a21\u578b\u7684\u7c7b\u578b\u7ea6\u675f\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u60f3\u5b9a\u4e49\u67d0\u4e9b\u5728\u5c5e\u6027\u8d4b\u503c\u4e0a\u9762\u6709\u9650\u5236\u7684\u6570\u636e\u7ed3\u6784\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5728\u8fd9\u4e2a\u95ee\u9898\u4e2d\uff0c\u4f60\u9700\u8981\u5728\u5bf9\u67d0\u4e9b\u5b9e\u4f8b\u5c5e\u6027\u8d4b\u503c\u65f6\u8fdb\u884c\u68c0\u67e5\u3002\n\u6240\u4ee5\u4f60\u8981\u81ea\u5b9a\u4e49\u5c5e\u6027\u8d4b\u503c\u51fd\u6570\uff0c\u8fd9\u79cd\u60c5\u51b5\u4e0b\u6700\u597d\u4f7f\u7528\u63cf\u8ff0\u5668\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e0b\u9762\u7684\u4ee3\u7801\u4f7f\u7528\u63cf\u8ff0\u5668\u5b9e\u73b0\u4e86\u4e00\u4e2a\u7cfb\u7edf\u7c7b\u578b\u548c\u8d4b\u503c\u9a8c\u8bc1\u6846\u67b6\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# Base class. Uses a descriptor to set a value\nclass Descriptor:\n    def __init__(self, name=None, **opts):\n        self.name = name\n        for key, value in opts.items():\n            setattr(self, key, value)\n\n    def __set__(self, instance, value):\n        instance.__dict__[self.name] = value\n\n\n# Descriptor for enforcing types\nclass Typed(Descriptor):\n    expected_type = type(None)\n\n    def __set__(self, instance, value):\n        if not isinstance(value, self.expected_type):\n            raise TypeError('expected ' + str(self.expected_type))\n        super().__set__(instance, value)\n\n\n# Descriptor for enforcing values\nclass Unsigned(Descriptor):\n    def __set__(self, instance, value):\n        if value < 0:\n            raise ValueError('Expected >= 0')\n        super().__set__(instance, value)\n\n\nclass MaxSized(Descriptor):\n    def __init__(self, name=None, **opts):\n        if 'size' not in opts:\n            raise TypeError('missing size option')\n        super().__init__(name, **opts)\n\n    def __set__(self, instance, value):\n        if len(value) >= self.size:\n            raise ValueError('size must be < ' + str(self.size))\n        super().__set__(instance, value)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u4e9b\u7c7b\u5c31\u662f\u4f60\u8981\u521b\u5efa\u7684\u6570\u636e\u6a21\u578b\u6216\u7c7b\u578b\u7cfb\u7edf\u7684\u57fa\u7840\u6784\u5efa\u6a21\u5757\u3002\n\u4e0b\u9762\u5c31\u662f\u6211\u4eec\u5b9e\u9645\u5b9a\u4e49\u7684\u5404\u79cd\u4e0d\u540c\u7684\u6570\u636e\u7c7b\u578b\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class Integer(Typed):\n    expected_type = int\n\nclass UnsignedInteger(Integer, Unsigned):\n    pass\n\nclass Float(Typed):\n    expected_type = float\n\nclass UnsignedFloat(Float, Unsigned):\n    pass\n\nclass String(Typed):\n    expected_type = str\n\nclass SizedString(String, MaxSized):\n    pass"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u7136\u540e\u4f7f\u7528\u8fd9\u4e9b\u81ea\u5b9a\u4e49\u6570\u636e\u7c7b\u578b\uff0c\u6211\u4eec\u5b9a\u4e49\u4e00\u4e2a\u7c7b\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class Stock:\n    # Specify constraints\n    name = SizedString('name', size=8)\n    shares = UnsignedInteger('shares')\n    price = UnsignedFloat('price')\n\n    def __init__(self, name, shares, price):\n        self.name = name\n        self.shares = shares\n        self.price = price"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u7136\u540e\u6d4b\u8bd5\u8fd9\u4e2a\u7c7b\u7684\u5c5e\u6027\u8d4b\u503c\u7ea6\u675f\uff0c\u53ef\u53d1\u73b0\u5bf9\u67d0\u4e9b\u5c5e\u6027\u7684\u8d4b\u503c\u8fdd\u6cd5\u4e86\u7ea6\u675f\u662f\u4e0d\u5408\u6cd5\u7684\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "s.name"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "s.shares = 75\ns.shares = -10"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "s.price = 'a lot'"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "s.name = 'ABRACADABRA'"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd8\u6709\u4e00\u4e9b\u6280\u672f\u53ef\u4ee5\u7b80\u5316\u4e0a\u9762\u7684\u4ee3\u7801\uff0c\u5176\u4e2d\u4e00\u79cd\u662f\u4f7f\u7528\u7c7b\u88c5\u9970\u5668\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# Class decorator to apply constraints\ndef check_attributes(**kwargs):\n    def decorate(cls):\n        for key, value in kwargs.items():\n            if isinstance(value, Descriptor):\n                value.name = key\n                setattr(cls, key, value)\n            else:\n                setattr(cls, key, value(key))\n        return cls\n\n    return decorate\n\n# Example\n@check_attributes(name=SizedString(size=8),\n                  shares=UnsignedInteger,\n                  price=UnsignedFloat)\nclass Stock:\n    def __init__(self, name, shares, price):\n        self.name = name\n        self.shares = shares\n        self.price = price"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u53e6\u5916\u4e00\u79cd\u65b9\u5f0f\u662f\u4f7f\u7528\u5143\u7c7b\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# A metaclass that applies checking\nclass checkedmeta(type):\n    def __new__(cls, clsname, bases, methods):\n        # Attach attribute names to the descriptors\n        for key, value in methods.items():\n            if isinstance(value, Descriptor):\n                value.name = key\n        return type.__new__(cls, clsname, bases, methods)\n\n# Example\nclass Stock2(metaclass=checkedmeta):\n    name = SizedString(size=8)\n    shares = UnsignedInteger()\n    price = UnsignedFloat()\n\n    def __init__(self, name, shares, price):\n        self.name = name\n        self.shares = shares\n        self.price = price"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u672c\u8282\u4f7f\u7528\u4e86\u5f88\u591a\u9ad8\u7ea7\u6280\u672f\uff0c\u5305\u62ec\u63cf\u8ff0\u5668\u3001\u6df7\u5165\u7c7b\u3001super() \u7684\u4f7f\u7528\u3001\u7c7b\u88c5\u9970\u5668\u548c\u5143\u7c7b\u3002\n\u4e0d\u53ef\u80fd\u5728\u8fd9\u91cc\u4e00\u4e00\u8be6\u7ec6\u5c55\u5f00\u6765\u8bb2\uff0c\u4f46\u662f\u53ef\u4ee5\u57288.9\u30018.18\u30019.19\u5c0f\u8282\u627e\u5230\u66f4\u591a\u4f8b\u5b50\u3002\n\u4f46\u662f\uff0c\u6211\u5728\u8fd9\u91cc\u8fd8\u662f\u8981\u63d0\u4e00\u4e0b\u51e0\u4e2a\u9700\u8981\u6ce8\u610f\u7684\u70b9\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u9996\u5148\uff0c\u5728 Descriptor \u57fa\u7c7b\u4e2d\u4f60\u4f1a\u770b\u5230\u6709\u4e2a __set__() \u65b9\u6cd5\uff0c\u5374\u6ca1\u6709\u76f8\u5e94\u7684 __get__() \u65b9\u6cd5\u3002\n\u5982\u679c\u4e00\u4e2a\u63cf\u8ff0\u4ec5\u4ec5\u662f\u4ece\u5e95\u5c42\u5b9e\u4f8b\u5b57\u5178\u4e2d\u83b7\u53d6\u67d0\u4e2a\u5c5e\u6027\u503c\u7684\u8bdd\uff0c\u90a3\u4e48\u6ca1\u5fc5\u8981\u53bb\u5b9a\u4e49 __get__() \u65b9\u6cd5\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u6240\u6709\u63cf\u8ff0\u5668\u7c7b\u90fd\u662f\u57fa\u4e8e\u6df7\u5165\u7c7b\u6765\u5b9e\u73b0\u7684\u3002\u6bd4\u5982 Unsigned \u548c MaxSized \u8981\u8ddf\u5176\u4ed6\u7ee7\u627f\u81ea Typed \u7c7b\u6df7\u5165\u3002\n\u8fd9\u91cc\u5229\u7528\u591a\u7ee7\u627f\u6765\u5b9e\u73b0\u76f8\u5e94\u7684\u529f\u80fd\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u6df7\u5165\u7c7b\u7684\u4e00\u4e2a\u6bd4\u8f83\u96be\u7406\u89e3\u7684\u5730\u65b9\u662f\uff0c\u8c03\u7528 super() \u51fd\u6570\u65f6\uff0c\u4f60\u5e76\u4e0d\u77e5\u9053\u7a76\u7adf\u8981\u8c03\u7528\u54ea\u4e2a\u5177\u4f53\u7c7b\u3002\n\u4f60\u9700\u8981\u8ddf\u5176\u4ed6\u7c7b\u7ed3\u5408\u540e\u624d\u80fd\u6b63\u786e\u7684\u4f7f\u7528\uff0c\u4e5f\u5c31\u662f\u5fc5\u987b\u5408\u4f5c\u624d\u80fd\u4ea7\u751f\u6548\u679c\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f7f\u7528\u7c7b\u88c5\u9970\u5668\u548c\u5143\u7c7b\u901a\u5e38\u53ef\u4ee5\u7b80\u5316\u4ee3\u7801\u3002\u4e0a\u9762\u4e24\u4e2a\u4f8b\u5b50\u4e2d\u4f60\u4f1a\u53d1\u73b0\u4f60\u53ea\u9700\u8981\u8f93\u5165\u4e00\u6b21\u5c5e\u6027\u540d\u5373\u53ef\u4e86\u3002"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# Normal\nclass Point:\n    x = Integer('x')\n    y = Integer('y')\n\n# Metaclass\nclass Point(metaclass=checkedmeta):\n    x = Integer()\n    y = Integer()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u6240\u6709\u65b9\u6cd5\u4e2d\uff0c\u7c7b\u88c5\u9970\u5668\u65b9\u6848\u5e94\u8be5\u662f\u6700\u7075\u6d3b\u548c\u6700\u9ad8\u660e\u7684\u3002\n\u9996\u5148\uff0c\u5b83\u5e76\u4e0d\u4f9d\u8d56\u4efb\u4f55\u5176\u4ed6\u65b0\u7684\u6280\u672f\uff0c\u6bd4\u5982\u5143\u7c7b\u3002\u5176\u6b21\uff0c\u88c5\u9970\u5668\u53ef\u4ee5\u5f88\u5bb9\u6613\u7684\u6dfb\u52a0\u6216\u5220\u9664\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u6700\u540e\uff0c\u88c5\u9970\u5668\u8fd8\u80fd\u4f5c\u4e3a\u6df7\u5165\u7c7b\u7684\u66ff\u4ee3\u6280\u672f\u6765\u5b9e\u73b0\u540c\u6837\u7684\u6548\u679c;"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# Decorator for applying type checking\ndef Typed(expected_type, cls=None):\n    if cls is None:\n        return lambda cls: Typed(expected_type, cls)\n    super_set = cls.__set__\n\n    def __set__(self, instance, value):\n        if not isinstance(value, expected_type):\n            raise TypeError('expected ' + str(expected_type))\n        super_set(self, instance, value)\n\n    cls.__set__ = __set__\n    return cls\n\n\n# Decorator for unsigned values\ndef Unsigned(cls):\n    super_set = cls.__set__\n\n    def __set__(self, instance, value):\n        if value < 0:\n            raise ValueError('Expected >= 0')\n        super_set(self, instance, value)\n\n    cls.__set__ = __set__\n    return cls\n\n\n# Decorator for allowing sized values\ndef MaxSized(cls):\n    super_init = cls.__init__\n\n    def __init__(self, name=None, **opts):\n        if 'size' not in opts:\n            raise TypeError('missing size option')\n        super_init(self, name, **opts)\n\n    cls.__init__ = __init__\n\n    super_set = cls.__set__\n\n    def __set__(self, instance, value):\n        if len(value) >= self.size:\n            raise ValueError('size must be < ' + str(self.size))\n        super_set(self, instance, value)\n\n    cls.__set__ = __set__\n    return cls\n\n\n# Specialized descriptors\n@Typed(int)\nclass Integer(Descriptor):\n    pass\n\n\n@Unsigned\nclass UnsignedInteger(Integer):\n    pass\n\n\n@Typed(float)\nclass Float(Descriptor):\n    pass\n\n\n@Unsigned\nclass UnsignedFloat(Float):\n    pass\n\n\n@Typed(str)\nclass String(Descriptor):\n    pass\n\n\n@MaxSized\nclass SizedString(String):\n    pass"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u79cd\u65b9\u5f0f\u5b9a\u4e49\u7684\u7c7b\u8ddf\u4e4b\u524d\u7684\u6548\u679c\u4e00\u6837\uff0c\u800c\u4e14\u6267\u884c\u901f\u5ea6\u4f1a\u66f4\u5feb\u3002\n\u8bbe\u7f6e\u4e00\u4e2a\u7b80\u5355\u7684\u7c7b\u578b\u5c5e\u6027\u7684\u503c\uff0c\u88c5\u9970\u5668\u65b9\u5f0f\u8981\u6bd4\u4e4b\u524d\u7684\u6df7\u5165\u7c7b\u7684\u65b9\u5f0f\u51e0\u4e4e\u5feb100%\u3002\n\u73b0\u5728\u4f60\u5e94\u8be5\u5e86\u5e78\u81ea\u5df1\u8bfb\u5b8c\u4e86\u672c\u8282\u5168\u90e8\u5185\u5bb9\u4e86\u5427\uff1f^_^"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 8.14 \u5b9e\u73b0\u81ea\u5b9a\u4e49\u5bb9\u5668\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u60f3\u5b9e\u73b0\u4e00\u4e2a\u81ea\u5b9a\u4e49\u7684\u7c7b\u6765\u6a21\u62df\u5185\u7f6e\u7684\u5bb9\u5668\u7c7b\u529f\u80fd\uff0c\u6bd4\u5982\u5217\u8868\u548c\u5b57\u5178\u3002\u4f46\u662f\u4f60\u4e0d\u786e\u5b9a\u5230\u5e95\u8981\u5b9e\u73b0\u54ea\u4e9b\u65b9\u6cd5\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "collections \u5b9a\u4e49\u4e86\u5f88\u591a\u62bd\u8c61\u57fa\u7c7b\uff0c\u5f53\u4f60\u60f3\u81ea\u5b9a\u4e49\u5bb9\u5668\u7c7b\u7684\u65f6\u5019\u5b83\u4eec\u4f1a\u975e\u5e38\u6709\u7528\u3002\n\u6bd4\u5982\u4f60\u60f3\u8ba9\u4f60\u7684\u7c7b\u652f\u6301\u8fed\u4ee3\uff0c\u90a3\u5c31\u8ba9\u4f60\u7684\u7c7b\u7ee7\u627f collections.Iterable \u5373\u53ef\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import collections\nclass A(collections.Iterable):\n    pass"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e0d\u8fc7\u4f60\u9700\u8981\u5b9e\u73b0 collections.Iterable \u6240\u6709\u7684\u62bd\u8c61\u65b9\u6cd5\uff0c\u5426\u5219\u4f1a\u62a5\u9519:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "a = A()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u53ea\u8981\u5b9e\u73b0 __iter__() \u65b9\u6cd5\u5c31\u4e0d\u4f1a\u62a5\u9519\u4e86(\u53c2\u80034.2\u548c4.7\u5c0f\u8282)\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u53ef\u4ee5\u5148\u8bd5\u7740\u53bb\u5b9e\u4f8b\u5316\u4e00\u4e2a\u5bf9\u8c61\uff0c\u5728\u9519\u8bef\u63d0\u793a\u4e2d\u53ef\u4ee5\u627e\u5230\u9700\u8981\u5b9e\u73b0\u54ea\u4e9b\u65b9\u6cd5\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import collections\ncollections.Sequence()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e0b\u9762\u662f\u4e00\u4e2a\u7b80\u5355\u7684\u793a\u4f8b\uff0c\u7ee7\u627f\u81ea\u4e0a\u9762Sequence\u62bd\u8c61\u7c7b\uff0c\u5e76\u4e14\u5b9e\u73b0\u5143\u7d20\u6309\u7167\u987a\u5e8f\u5b58\u50a8\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class SortedItems(collections.Sequence):\n    def __init__(self, initial=None):\n        self._items = sorted(initial) if initial is not None else []\n\n    # Required sequence methods\n    def __getitem__(self, index):\n        return self._items[index]\n\n    def __len__(self):\n        return len(self._items)\n\n    # Method for adding an item in the right location\n    def add(self, item):\n        bisect.insort(self._items, item)\n\n\nitems = SortedItems([5, 1, 3])\nprint(list(items))\nprint(items[0], items[-1])\nitems.add(2)\nprint(list(items))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u53ef\u4ee5\u770b\u5230\uff0cSortedItems\u8ddf\u666e\u901a\u7684\u5e8f\u5217\u6ca1\u4ec0\u4e48\u4e24\u6837\uff0c\u652f\u6301\u6240\u6709\u5e38\u7528\u64cd\u4f5c\uff0c\u5305\u62ec\u7d22\u5f15\u3001\u8fed\u4ee3\u3001\u5305\u542b\u5224\u65ad\uff0c\u751a\u81f3\u662f\u5207\u7247\u64cd\u4f5c\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u91cc\u9762\u4f7f\u7528\u5230\u4e86 bisect \u6a21\u5757\uff0c\u5b83\u662f\u4e00\u4e2a\u5728\u6392\u5e8f\u5217\u8868\u4e2d\u63d2\u5165\u5143\u7d20\u7684\u9ad8\u6548\u65b9\u5f0f\u3002\u53ef\u4ee5\u4fdd\u8bc1\u5143\u7d20\u63d2\u5165\u540e\u8fd8\u4fdd\u6301\u987a\u5e8f\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f7f\u7528 collections \u4e2d\u7684\u62bd\u8c61\u57fa\u7c7b\u53ef\u4ee5\u786e\u4fdd\u4f60\u81ea\u5b9a\u4e49\u7684\u5bb9\u5668\u5b9e\u73b0\u4e86\u6240\u6709\u5fc5\u8981\u7684\u65b9\u6cd5\u3002\u5e76\u4e14\u8fd8\u80fd\u7b80\u5316\u7c7b\u578b\u68c0\u67e5\u3002\n\u4f60\u7684\u81ea\u5b9a\u4e49\u5bb9\u5668\u4f1a\u6ee1\u8db3\u5927\u90e8\u5206\u7c7b\u578b\u68c0\u67e5\u9700\u8981\uff0c\u5982\u4e0b\u6240\u793a\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "items = SortedItems()\nimport collections\nisinstance(items, collections.Iterable)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "isinstance(items, collections.Sequence)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "isinstance(items, collections.Container)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "isinstance(items, collections.Sized)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "isinstance(items, collections.Mapping)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "collections \u4e2d\u5f88\u591a\u62bd\u8c61\u7c7b\u4f1a\u4e3a\u4e00\u4e9b\u5e38\u89c1\u5bb9\u5668\u64cd\u4f5c\u63d0\u4f9b\u9ed8\u8ba4\u7684\u5b9e\u73b0\uff0c\n\u8fd9\u6837\u4e00\u6765\u4f60\u53ea\u9700\u8981\u5b9e\u73b0\u90a3\u4e9b\u4f60\u6700\u611f\u5174\u8da3\u7684\u65b9\u6cd5\u5373\u53ef\u3002\u5047\u8bbe\u4f60\u7684\u7c7b\u7ee7\u627f\u81ea collections.MutableSequence \uff0c\u5982\u4e0b\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class Items(collections.MutableSequence):\n    def __init__(self, initial=None):\n        self._items = list(initial) if initial is not None else []\n\n    # Required sequence methods\n    def __getitem__(self, index):\n        print('Getting:', index)\n        return self._items[index]\n\n    def __setitem__(self, index, value):\n        print('Setting:', index, value)\n        self._items[index] = value\n\n    def __delitem__(self, index):\n        print('Deleting:', index)\n        del self._items[index]\n\n    def insert(self, index, value):\n        print('Inserting:', index, value)\n        self._items.insert(index, value)\n\n    def __len__(self):\n        print('Len')\n        return len(self._items)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u4f60\u521b\u5efa Items \u7684\u5b9e\u4f8b\uff0c\u4f60\u4f1a\u53d1\u73b0\u5b83\u652f\u6301\u51e0\u4e4e\u6240\u6709\u7684\u6838\u5fc3\u5217\u8868\u65b9\u6cd5(\u5982append()\u3001remove()\u3001count()\u7b49)\u3002\n\u4e0b\u9762\u662f\u4f7f\u7528\u6f14\u793a\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "a = Items([1, 2, 3])\nlen(a)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "a.append(4)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "a.append(2)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "a.count(2)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "a.remove(3)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u672c\u5c0f\u8282\u53ea\u662f\u5bf9Python\u62bd\u8c61\u7c7b\u529f\u80fd\u7684\u629b\u7816\u5f15\u7389\u3002numbers \u6a21\u5757\u63d0\u4f9b\u4e86\u4e00\u4e2a\u7c7b\u4f3c\u7684\u8ddf\u6574\u6570\u7c7b\u578b\u76f8\u5173\u7684\u62bd\u8c61\u7c7b\u578b\u96c6\u5408\u3002\n\u53ef\u4ee5\u53c2\u80038.12\u5c0f\u8282\u6765\u6784\u9020\u66f4\u591a\u81ea\u5b9a\u4e49\u62bd\u8c61\u57fa\u7c7b\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 8.15 \u5c5e\u6027\u7684\u4ee3\u7406\u8bbf\u95ee\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u60f3\u5c06\u67d0\u4e2a\u5b9e\u4f8b\u7684\u5c5e\u6027\u8bbf\u95ee\u4ee3\u7406\u5230\u5185\u90e8\u53e6\u4e00\u4e2a\u5b9e\u4f8b\u4e2d\u53bb\uff0c\u76ee\u7684\u53ef\u80fd\u662f\u4f5c\u4e3a\u7ee7\u627f\u7684\u4e00\u4e2a\u66ff\u4ee3\u65b9\u6cd5\u6216\u8005\u5b9e\u73b0\u4ee3\u7406\u6a21\u5f0f\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u7b80\u5355\u6765\u8bf4\uff0c\u4ee3\u7406\u662f\u4e00\u79cd\u7f16\u7a0b\u6a21\u5f0f\uff0c\u5b83\u5c06\u67d0\u4e2a\u64cd\u4f5c\u8f6c\u79fb\u7ed9\u53e6\u5916\u4e00\u4e2a\u5bf9\u8c61\u6765\u5b9e\u73b0\u3002\n\u6700\u7b80\u5355\u7684\u5f62\u5f0f\u53ef\u80fd\u662f\u50cf\u4e0b\u9762\u8fd9\u6837\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class A:\n    def spam(self, x):\n        pass\n\n    def foo(self):\n        pass\n\n\nclass B1:\n    \"\"\"\u7b80\u5355\u7684\u4ee3\u7406\"\"\"\n\n    def __init__(self):\n        self._a = A()\n\n    def spam(self, x):\n        # Delegate to the internal self._a instance\n        return self._a.spam(x)\n\n    def foo(self):\n        # Delegate to the internal self._a instance\n        return self._a.foo()\n\n    def bar(self):\n        pass"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u4ec5\u4ec5\u5c31\u4e24\u4e2a\u65b9\u6cd5\u9700\u8981\u4ee3\u7406\uff0c\u90a3\u4e48\u50cf\u8fd9\u6837\u5199\u5c31\u8db3\u591f\u4e86\u3002\u4f46\u662f\uff0c\u5982\u679c\u6709\u5927\u91cf\u7684\u65b9\u6cd5\u9700\u8981\u4ee3\u7406\uff0c\n\u90a3\u4e48\u4f7f\u7528 __getattr__() \u65b9\u6cd5\u6216\u8bb8\u6216\u66f4\u597d\u4e9b\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class B2:\n    \"\"\"\u4f7f\u7528__getattr__\u7684\u4ee3\u7406\uff0c\u4ee3\u7406\u65b9\u6cd5\u6bd4\u8f83\u591a\u65f6\u5019\"\"\"\n\n    def __init__(self):\n        self._a = A()\n\n    def bar(self):\n        pass\n\n    # Expose all of the methods defined on class A\n    def __getattr__(self, name):\n        \"\"\"\u8fd9\u4e2a\u65b9\u6cd5\u5728\u8bbf\u95ee\u7684attribute\u4e0d\u5b58\u5728\u7684\u65f6\u5019\u88ab\u8c03\u7528\n        the __getattr__() method is actually a fallback method\n        that only gets called when an attribute is not found\"\"\"\n        return getattr(self._a, name)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "__getattr__ \u65b9\u6cd5\u662f\u5728\u8bbf\u95eeattribute\u4e0d\u5b58\u5728\u7684\u65f6\u5019\u88ab\u8c03\u7528\uff0c\u4f7f\u7528\u6f14\u793a\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "b = B()\nb.bar() # Calls B.bar() (exists on B)\nb.spam(42) # Calls B.__getattr__('spam') and delegates to A.spam"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u53e6\u5916\u4e00\u4e2a\u4ee3\u7406\u4f8b\u5b50\u662f\u5b9e\u73b0\u4ee3\u7406\u6a21\u5f0f\uff0c\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# A proxy class that wraps around another object, but\n# exposes its public attributes\nclass Proxy:\n    def __init__(self, obj):\n        self._obj = obj\n\n    # Delegate attribute lookup to internal obj\n    def __getattr__(self, name):\n        print('getattr:', name)\n        return getattr(self._obj, name)\n\n    # Delegate attribute assignment\n    def __setattr__(self, name, value):\n        if name.startswith('_'):\n            super().__setattr__(name, value)\n        else:\n            print('setattr:', name, value)\n            setattr(self._obj, name, value)\n\n    # Delegate attribute deletion\n    def __delattr__(self, name):\n        if name.startswith('_'):\n            super().__delattr__(name)\n        else:\n            print('delattr:', name)\n            delattr(self._obj, name)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f7f\u7528\u8fd9\u4e2a\u4ee3\u7406\u7c7b\u65f6\uff0c\u4f60\u53ea\u9700\u8981\u7528\u5b83\u6765\u5305\u88c5\u4e0b\u5176\u4ed6\u7c7b\u5373\u53ef\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class Spam:\n    def __init__(self, x):\n        self.x = x\n\n    def bar(self, y):\n        print('Spam.bar:', self.x, y)\n\n# Create an instance\ns = Spam(2)\n# Create a proxy around it\np = Proxy(s)\n# Access the proxy\nprint(p.x)  # Outputs 2\np.bar(3)  # Outputs \"Spam.bar: 2 3\"\np.x = 37  # Changes s.x to 37"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u901a\u8fc7\u81ea\u5b9a\u4e49\u5c5e\u6027\u8bbf\u95ee\u65b9\u6cd5\uff0c\u4f60\u53ef\u4ee5\u7528\u4e0d\u540c\u65b9\u5f0f\u81ea\u5b9a\u4e49\u4ee3\u7406\u7c7b\u884c\u4e3a(\u6bd4\u5982\u52a0\u5165\u65e5\u5fd7\u529f\u80fd\u3001\u53ea\u8bfb\u8bbf\u95ee\u7b49)\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4ee3\u7406\u7c7b\u6709\u65f6\u5019\u53ef\u4ee5\u4f5c\u4e3a\u7ee7\u627f\u7684\u66ff\u4ee3\u65b9\u6848\u3002\u4f8b\u5982\uff0c\u4e00\u4e2a\u7b80\u5355\u7684\u7ee7\u627f\u5982\u4e0b\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class A:\n    def spam(self, x):\n        print('A.spam', x)\n    def foo(self):\n        print('A.foo')\n\nclass B(A):\n    def spam(self, x):\n        print('B.spam')\n        super().spam(x)\n    def bar(self):\n        print('B.bar')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f7f\u7528\u4ee3\u7406\u7684\u8bdd\uff0c\u5c31\u662f\u4e0b\u9762\u8fd9\u6837\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class A:\n    def spam(self, x):\n        print('A.spam', x)\n    def foo(self):\n        print('A.foo')\n\nclass B:\n    def __init__(self):\n        self._a = A()\n    def spam(self, x):\n        print('B.spam', x)\n        self._a.spam(x)\n    def bar(self):\n        print('B.bar')\n    def __getattr__(self, name):\n        return getattr(self._a, name)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5f53\u5b9e\u73b0\u4ee3\u7406\u6a21\u5f0f\u65f6\uff0c\u8fd8\u6709\u4e9b\u7ec6\u8282\u9700\u8981\u6ce8\u610f\u3002\n\u9996\u5148\uff0c__getattr__() \u5b9e\u9645\u662f\u4e00\u4e2a\u540e\u5907\u65b9\u6cd5\uff0c\u53ea\u6709\u5728\u5c5e\u6027\u4e0d\u5b58\u5728\u65f6\u624d\u4f1a\u8c03\u7528\u3002\n\u56e0\u6b64\uff0c\u5982\u679c\u4ee3\u7406\u7c7b\u5b9e\u4f8b\u672c\u8eab\u6709\u8fd9\u4e2a\u5c5e\u6027\u7684\u8bdd\uff0c\u90a3\u4e48\u4e0d\u4f1a\u89e6\u53d1\u8fd9\u4e2a\u65b9\u6cd5\u7684\u3002\n\u53e6\u5916\uff0c__setattr__() \u548c __delattr__() \u9700\u8981\u989d\u5916\u7684\u9b54\u6cd5\u6765\u533a\u5206\u4ee3\u7406\u5b9e\u4f8b\u548c\u88ab\u4ee3\u7406\u5b9e\u4f8b _obj \u7684\u5c5e\u6027\u3002\n\u4e00\u4e2a\u901a\u5e38\u7684\u7ea6\u5b9a\u662f\u53ea\u4ee3\u7406\u90a3\u4e9b\u4e0d\u4ee5\u4e0b\u5212\u7ebf _ \u5f00\u5934\u7684\u5c5e\u6027(\u4ee3\u7406\u7c7b\u53ea\u66b4\u9732\u88ab\u4ee3\u7406\u7c7b\u7684\u516c\u5171\u5c5e\u6027)\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd8\u6709\u4e00\u70b9\u9700\u8981\u6ce8\u610f\u7684\u662f\uff0c__getattr__() \u5bf9\u4e8e\u5927\u90e8\u5206\u4ee5\u53cc\u4e0b\u5212\u7ebf(__)\u5f00\u59cb\u548c\u7ed3\u5c3e\u7684\u5c5e\u6027\u5e76\u4e0d\u9002\u7528\u3002\n\u6bd4\u5982\uff0c\u8003\u8651\u5982\u4e0b\u7684\u7c7b\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class ListLike:\n    \"\"\"__getattr__\u5bf9\u4e8e\u53cc\u4e0b\u5212\u7ebf\u5f00\u59cb\u548c\u7ed3\u5c3e\u7684\u65b9\u6cd5\u662f\u4e0d\u80fd\u7528\u7684\uff0c\u9700\u8981\u4e00\u4e2a\u4e2a\u53bb\u91cd\u5b9a\u4e49\"\"\"\n\n    def __init__(self):\n        self._items = []\n\n    def __getattr__(self, name):\n        return getattr(self._items, name)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u662f\u521b\u5efa\u4e00\u4e2aListLike\u5bf9\u8c61\uff0c\u4f1a\u53d1\u73b0\u5b83\u652f\u6301\u666e\u901a\u7684\u5217\u8868\u65b9\u6cd5\uff0c\u5982append()\u548cinsert()\uff0c\n\u4f46\u662f\u5374\u4e0d\u652f\u6301len()\u3001\u5143\u7d20\u67e5\u627e\u7b49\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "a = ListLike()\na.append(2)\na.insert(0, 1)\na.sort()\nlen(a)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "a[0]"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e3a\u4e86\u8ba9\u5b83\u652f\u6301\u8fd9\u4e9b\u65b9\u6cd5\uff0c\u4f60\u5fc5\u987b\u624b\u52a8\u7684\u5b9e\u73b0\u8fd9\u4e9b\u65b9\u6cd5\u4ee3\u7406\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class ListLike:\n    \"\"\"__getattr__\u5bf9\u4e8e\u53cc\u4e0b\u5212\u7ebf\u5f00\u59cb\u548c\u7ed3\u5c3e\u7684\u65b9\u6cd5\u662f\u4e0d\u80fd\u7528\u7684\uff0c\u9700\u8981\u4e00\u4e2a\u4e2a\u53bb\u91cd\u5b9a\u4e49\"\"\"\n\n    def __init__(self):\n        self._items = []\n\n    def __getattr__(self, name):\n        return getattr(self._items, name)\n\n    # Added special methods to support certain list operations\n    def __len__(self):\n        return len(self._items)\n\n    def __getitem__(self, index):\n        return self._items[index]\n\n    def __setitem__(self, index, value):\n        self._items[index] = value\n\n    def __delitem__(self, index):\n        del self._items[index]"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "11.8\u5c0f\u8282\u8fd8\u6709\u4e00\u4e2a\u5728\u8fdc\u7a0b\u65b9\u6cd5\u8c03\u7528\u73af\u5883\u4e2d\u4f7f\u7528\u4ee3\u7406\u7684\u4f8b\u5b50\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 8.16 \u5728\u7c7b\u4e2d\u5b9a\u4e49\u591a\u4e2a\u6784\u9020\u5668\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u60f3\u5b9e\u73b0\u4e00\u4e2a\u7c7b\uff0c\u9664\u4e86\u4f7f\u7528 __init__() \u65b9\u6cd5\u5916\uff0c\u8fd8\u6709\u5176\u4ed6\u65b9\u5f0f\u53ef\u4ee5\u521d\u59cb\u5316\u5b83\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e3a\u4e86\u5b9e\u73b0\u591a\u4e2a\u6784\u9020\u5668\uff0c\u4f60\u9700\u8981\u4f7f\u7528\u5230\u7c7b\u65b9\u6cd5\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import time\n\nclass Date:\n    \"\"\"\u65b9\u6cd5\u4e00\uff1a\u4f7f\u7528\u7c7b\u65b9\u6cd5\"\"\"\n    # Primary constructor\n    def __init__(self, year, month, day):\n        self.year = year\n        self.month = month\n        self.day = day\n\n    # Alternate constructor\n    @classmethod\n    def today(cls):\n        t = time.localtime()\n        return cls(t.tm_year, t.tm_mon, t.tm_mday)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u76f4\u63a5\u8c03\u7528\u7c7b\u65b9\u6cd5\u5373\u53ef\uff0c\u4e0b\u9762\u662f\u4f7f\u7528\u793a\u4f8b\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "a = Date(2012, 12, 21) # Primary\nb = Date.today() # Alternate"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u7c7b\u65b9\u6cd5\u7684\u4e00\u4e2a\u4e3b\u8981\u7528\u9014\u5c31\u662f\u5b9a\u4e49\u591a\u4e2a\u6784\u9020\u5668\u3002\u5b83\u63a5\u53d7\u4e00\u4e2a class \u4f5c\u4e3a\u7b2c\u4e00\u4e2a\u53c2\u6570(cls)\u3002\n\u4f60\u5e94\u8be5\u6ce8\u610f\u5230\u4e86\u8fd9\u4e2a\u7c7b\u88ab\u7528\u6765\u521b\u5efa\u5e76\u8fd4\u56de\u6700\u7ec8\u7684\u5b9e\u4f8b\u3002\u5728\u7ee7\u627f\u65f6\u4e5f\u80fd\u5de5\u4f5c\u7684\u5f88\u597d\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class NewDate(Date):\n    pass\n\nc = Date.today() # Creates an instance of Date (cls=Date)\nd = NewDate.today() # Creates an instance of NewDate (cls=NewDate)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 8.17 \u521b\u5efa\u4e0d\u8c03\u7528init\u65b9\u6cd5\u7684\u5b9e\u4f8b\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u60f3\u521b\u5efa\u4e00\u4e2a\u5b9e\u4f8b\uff0c\u4f46\u662f\u5e0c\u671b\u7ed5\u8fc7\u6267\u884c __init__() \u65b9\u6cd5\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u53ef\u4ee5\u901a\u8fc7 __new__() \u65b9\u6cd5\u521b\u5efa\u4e00\u4e2a\u672a\u521d\u59cb\u5316\u7684\u5b9e\u4f8b\u3002\u4f8b\u5982\u8003\u8651\u5982\u4e0b\u8fd9\u4e2a\u7c7b\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class Date:\n    def __init__(self, year, month, day):\n        self.year = year\n        self.month = month\n        self.day = day"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e0b\u9762\u6f14\u793a\u5982\u4f55\u4e0d\u8c03\u7528 __init__() \u65b9\u6cd5\u6765\u521b\u5efa\u8fd9\u4e2aDate\u5b9e\u4f8b\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "d = Date.__new__(Date)\nd"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "d.year"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u7ed3\u679c\u53ef\u4ee5\u770b\u5230\uff0c\u8fd9\u4e2aDate\u5b9e\u4f8b\u7684\u5c5e\u6027year\u8fd8\u4e0d\u5b58\u5728\uff0c\u6240\u4ee5\u4f60\u9700\u8981\u624b\u52a8\u521d\u59cb\u5316\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "data = {'year':2012, 'month':8, 'day':29}\nfor key, value in data.items():\n    setattr(d, key, value)\nd.year"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "d.month"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5f53\u6211\u4eec\u5728\u53cd\u5e8f\u5217\u5bf9\u8c61\u6216\u8005\u5b9e\u73b0\u67d0\u4e2a\u7c7b\u65b9\u6cd5\u6784\u9020\u51fd\u6570\u65f6\u9700\u8981\u7ed5\u8fc7 __init__() \u65b9\u6cd5\u6765\u521b\u5efa\u5bf9\u8c61\u3002\n\u4f8b\u5982\uff0c\u5bf9\u4e8e\u4e0a\u9762\u7684Date\u6765\u8bb2\uff0c\u6709\u65f6\u5019\u4f60\u53ef\u80fd\u4f1a\u50cf\u4e0b\u9762\u8fd9\u6837\u5b9a\u4e49\u4e00\u4e2a\u65b0\u7684\u6784\u9020\u51fd\u6570 today() \uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "from time import localtime\n\nclass Date:\n    def __init__(self, year, month, day):\n        self.year = year\n        self.month = month\n        self.day = day\n\n    @classmethod\n    def today(cls):\n        d = cls.__new__(cls)\n        t = localtime()\n        d.year = t.tm_year\n        d.month = t.tm_mon\n        d.day = t.tm_mday\n        return d"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u540c\u6837\uff0c\u5728\u4f60\u53cd\u5e8f\u5217\u5316JSON\u6570\u636e\u65f6\u4ea7\u751f\u4e00\u4e2a\u5982\u4e0b\u7684\u5b57\u5178\u5bf9\u8c61\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "data = { 'year': 2012, 'month': 8, 'day': 29 }"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u4f60\u60f3\u5c06\u5b83\u8f6c\u6362\u6210\u4e00\u4e2aDate\u7c7b\u578b\u5b9e\u4f8b\uff0c\u53ef\u4ee5\u4f7f\u7528\u4e0a\u9762\u7684\u6280\u672f\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5f53\u4f60\u901a\u8fc7\u8fd9\u79cd\u975e\u5e38\u89c4\u65b9\u5f0f\u6765\u521b\u5efa\u5b9e\u4f8b\u7684\u65f6\u5019\uff0c\u6700\u597d\u4e0d\u8981\u76f4\u63a5\u53bb\u8bbf\u95ee\u5e95\u5c42\u5b9e\u4f8b\u5b57\u5178\uff0c\u9664\u975e\u4f60\u771f\u7684\u6e05\u695a\u6240\u6709\u7ec6\u8282\u3002\n\u5426\u5219\u7684\u8bdd\uff0c\u5982\u679c\u8fd9\u4e2a\u7c7b\u4f7f\u7528\u4e86 __slots__ \u3001properties \u3001descriptors \u6216\u5176\u4ed6\u9ad8\u7ea7\u6280\u672f\u7684\u65f6\u5019\u4ee3\u7801\u5c31\u4f1a\u5931\u6548\u3002\n\u800c\u8fd9\u65f6\u5019\u4f7f\u7528 setattr() \u65b9\u6cd5\u4f1a\u8ba9\u4f60\u7684\u4ee3\u7801\u53d8\u5f97\u66f4\u52a0\u901a\u7528\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 8.18 \u5229\u7528Mixins\u6269\u5c55\u7c7b\u529f\u80fd\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u6709\u5f88\u591a\u6709\u7528\u7684\u65b9\u6cd5\uff0c\u60f3\u4f7f\u7528\u5b83\u4eec\u6765\u6269\u5c55\u5176\u4ed6\u7c7b\u7684\u529f\u80fd\u3002\u4f46\u662f\u8fd9\u4e9b\u7c7b\u5e76\u6ca1\u6709\u4efb\u4f55\u7ee7\u627f\u7684\u5173\u7cfb\u3002\n\u56e0\u6b64\u4f60\u4e0d\u80fd\u7b80\u5355\u7684\u5c06\u8fd9\u4e9b\u65b9\u6cd5\u653e\u5165\u4e00\u4e2a\u57fa\u7c7b\uff0c\u7136\u540e\u88ab\u5176\u4ed6\u7c7b\u7ee7\u627f\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u901a\u5e38\u5f53\u4f60\u60f3\u81ea\u5b9a\u4e49\u7c7b\u7684\u65f6\u5019\u4f1a\u78b0\u4e0a\u8fd9\u4e9b\u95ee\u9898\u3002\u53ef\u80fd\u662f\u67d0\u4e2a\u5e93\u63d0\u4f9b\u4e86\u4e00\u4e9b\u57fa\u7840\u7c7b\uff0c\n\u4f60\u53ef\u4ee5\u5229\u7528\u5b83\u4eec\u6765\u6784\u9020\u4f60\u81ea\u5df1\u7684\u7c7b\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5047\u8bbe\u4f60\u60f3\u6269\u5c55\u6620\u5c04\u5bf9\u8c61\uff0c\u7ed9\u5b83\u4eec\u6dfb\u52a0\u65e5\u5fd7\u3001\u552f\u4e00\u6027\u8bbe\u7f6e\u3001\u7c7b\u578b\u68c0\u67e5\u7b49\u7b49\u529f\u80fd\u3002\u4e0b\u9762\u662f\u4e00\u4e9b\u6df7\u5165\u7c7b\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class LoggedMappingMixin:\n    \"\"\"\n    Add logging to get/set/delete operations for debugging.\n    \"\"\"\n    __slots__ = ()  # \u6df7\u5165\u7c7b\u90fd\u6ca1\u6709\u5b9e\u4f8b\u53d8\u91cf\uff0c\u56e0\u4e3a\u76f4\u63a5\u5b9e\u4f8b\u5316\u6df7\u5165\u7c7b\u6ca1\u6709\u4efb\u4f55\u610f\u4e49\n\n    def __getitem__(self, key):\n        print('Getting ' + str(key))\n        return super().__getitem__(key)\n\n    def __setitem__(self, key, value):\n        print('Setting {} = {!r}'.format(key, value))\n        return super().__setitem__(key, value)\n\n    def __delitem__(self, key):\n        print('Deleting ' + str(key))\n        return super().__delitem__(key)\n\n\nclass SetOnceMappingMixin:\n    '''\n    Only allow a key to be set once.\n    '''\n    __slots__ = ()\n\n    def __setitem__(self, key, value):\n        if key in self:\n            raise KeyError(str(key) + ' already set')\n        return super().__setitem__(key, value)\n\n\nclass StringKeysMappingMixin:\n    '''\n    Restrict keys to strings only\n    '''\n    __slots__ = ()\n\n    def __setitem__(self, key, value):\n        if not isinstance(key, str):\n            raise TypeError('keys must be strings')\n        return super().__setitem__(key, value)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u4e9b\u7c7b\u5355\u72ec\u4f7f\u7528\u8d77\u6765\u6ca1\u6709\u4efb\u4f55\u610f\u4e49\uff0c\u4e8b\u5b9e\u4e0a\u5982\u679c\u4f60\u53bb\u5b9e\u4f8b\u5316\u4efb\u4f55\u4e00\u4e2a\u7c7b\uff0c\u9664\u4e86\u4ea7\u751f\u5f02\u5e38\u5916\u6ca1\u4efb\u4f55\u4f5c\u7528\u3002\n\u5b83\u4eec\u662f\u7528\u6765\u901a\u8fc7\u591a\u7ee7\u627f\u6765\u548c\u5176\u4ed6\u6620\u5c04\u5bf9\u8c61\u6df7\u5165\u4f7f\u7528\u7684\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class LoggedDict(LoggedMappingMixin, dict):\n    pass\n\nd = LoggedDict()\nd['x'] = 23\nprint(d['x'])\ndel d['x']\n\nfrom collections import defaultdict\n\nclass SetOnceDefaultDict(SetOnceMappingMixin, defaultdict):\n    pass\n\n\nd = SetOnceDefaultDict(list)\nd['x'].append(2)\nd['x'].append(3)\n# d['x'] = 23  # KeyError: 'x already set'"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u4e2a\u4f8b\u5b50\u4e2d\uff0c\u53ef\u4ee5\u770b\u5230\u6df7\u5165\u7c7b\u8ddf\u5176\u4ed6\u5df2\u5b58\u5728\u7684\u7c7b(\u6bd4\u5982dict\u3001defaultdict\u548cOrderedDict)\u7ed3\u5408\u8d77\u6765\u4f7f\u7528\uff0c\u4e00\u4e2a\u63a5\u4e00\u4e2a\u3002\n\u7ed3\u5408\u540e\u5c31\u80fd\u53d1\u6325\u6b63\u5e38\u529f\u6548\u4e86\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u6df7\u5165\u7c7b\u5728\u6807\u51c6\u5e93\u4e2d\u5f88\u591a\u5730\u65b9\u90fd\u51fa\u73b0\u8fc7\uff0c\u901a\u5e38\u90fd\u662f\u7528\u6765\u50cf\u4e0a\u9762\u90a3\u6837\u6269\u5c55\u67d0\u4e9b\u7c7b\u7684\u529f\u80fd\u3002\n\u5b83\u4eec\u4e5f\u662f\u591a\u7ee7\u627f\u7684\u4e00\u4e2a\u4e3b\u8981\u7528\u9014\u3002\u6bd4\u5982\uff0c\u5f53\u4f60\u7f16\u5199\u7f51\u7edc\u4ee3\u7801\u65f6\u5019\uff0c\n\u4f60\u4f1a\u7ecf\u5e38\u4f7f\u7528 socketserver \u6a21\u5757\u4e2d\u7684 ThreadingMixIn \u6765\u7ed9\u5176\u4ed6\u7f51\u7edc\u76f8\u5173\u7c7b\u589e\u52a0\u591a\u7ebf\u7a0b\u652f\u6301\u3002\n\u4f8b\u5982\uff0c\u4e0b\u9762\u662f\u4e00\u4e2a\u591a\u7ebf\u7a0b\u7684XML-RPC\u670d\u52a1\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "from xmlrpc.server import SimpleXMLRPCServer\nfrom socketserver import ThreadingMixIn\nclass ThreadedXMLRPCServer(ThreadingMixIn, SimpleXMLRPCServer):\n    pass"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u540c\u65f6\u5728\u4e00\u4e9b\u5927\u578b\u5e93\u548c\u6846\u67b6\u4e2d\u4e5f\u4f1a\u53d1\u73b0\u6df7\u5165\u7c7b\u7684\u4f7f\u7528\uff0c\u7528\u9014\u540c\u6837\u662f\u589e\u5f3a\u5df2\u5b58\u5728\u7684\u7c7b\u7684\u529f\u80fd\u548c\u4e00\u4e9b\u53ef\u9009\u7279\u5f81\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5bf9\u4e8e\u6df7\u5165\u7c7b\uff0c\u6709\u51e0\u70b9\u9700\u8981\u8bb0\u4f4f\u3002\u9996\u5148\u662f\uff0c\u6df7\u5165\u7c7b\u4e0d\u80fd\u76f4\u63a5\u88ab\u5b9e\u4f8b\u5316\u4f7f\u7528\u3002\n\u5176\u6b21\uff0c\u6df7\u5165\u7c7b\u6ca1\u6709\u81ea\u5df1\u7684\u72b6\u6001\u4fe1\u606f\uff0c\u4e5f\u5c31\u662f\u8bf4\u5b83\u4eec\u5e76\u6ca1\u6709\u5b9a\u4e49 __init__() \u65b9\u6cd5\uff0c\u5e76\u4e14\u6ca1\u6709\u5b9e\u4f8b\u5c5e\u6027\u3002\n\u8fd9\u4e5f\u662f\u4e3a\u4ec0\u4e48\u6211\u4eec\u5728\u4e0a\u9762\u660e\u786e\u5b9a\u4e49\u4e86 __slots__ = () \u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd8\u6709\u4e00\u79cd\u5b9e\u73b0\u6df7\u5165\u7c7b\u7684\u65b9\u5f0f\u5c31\u662f\u4f7f\u7528\u7c7b\u88c5\u9970\u5668\uff0c\u5982\u4e0b\u6240\u793a\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "def LoggedMapping(cls):\n    \"\"\"\u7b2c\u4e8c\u79cd\u65b9\u5f0f\uff1a\u4f7f\u7528\u7c7b\u88c5\u9970\u5668\"\"\"\n    cls_getitem = cls.__getitem__\n    cls_setitem = cls.__setitem__\n    cls_delitem = cls.__delitem__\n\n    def __getitem__(self, key):\n        print('Getting ' + str(key))\n        return cls_getitem(self, key)\n\n    def __setitem__(self, key, value):\n        print('Setting {} = {!r}'.format(key, value))\n        return cls_setitem(self, key, value)\n\n    def __delitem__(self, key):\n        print('Deleting ' + str(key))\n        return cls_delitem(self, key)\n\n    cls.__getitem__ = __getitem__\n    cls.__setitem__ = __setitem__\n    cls.__delitem__ = __delitem__\n    return cls\n\n\n@LoggedMapping\nclass LoggedDict(dict):\n    pass"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u4e2a\u6548\u679c\u8ddf\u4e4b\u524d\u7684\u662f\u4e00\u6837\u7684\uff0c\u800c\u4e14\u4e0d\u518d\u9700\u8981\u4f7f\u7528\u591a\u7ee7\u627f\u4e86\u3002\u53c2\u80039.12\u5c0f\u8282\u83b7\u53d6\u66f4\u591a\u7c7b\u88c5\u9970\u5668\u7684\u4fe1\u606f\uff0c\n\u53c2\u80038.13\u5c0f\u8282\u67e5\u770b\u66f4\u591a\u6df7\u5165\u7c7b\u548c\u7c7b\u88c5\u9970\u5668\u7684\u4f8b\u5b50\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 8.19 \u5b9e\u73b0\u72b6\u6001\u5bf9\u8c61\u6216\u8005\u72b6\u6001\u673a\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u60f3\u5b9e\u73b0\u4e00\u4e2a\u72b6\u6001\u673a\u6216\u8005\u662f\u5728\u4e0d\u540c\u72b6\u6001\u4e0b\u6267\u884c\u64cd\u4f5c\u7684\u5bf9\u8c61\uff0c\u4f46\u662f\u53c8\u4e0d\u60f3\u5728\u4ee3\u7801\u4e2d\u51fa\u73b0\u592a\u591a\u7684\u6761\u4ef6\u5224\u65ad\u8bed\u53e5\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5728\u5f88\u591a\u7a0b\u5e8f\u4e2d\uff0c\u6709\u4e9b\u5bf9\u8c61\u4f1a\u6839\u636e\u72b6\u6001\u7684\u4e0d\u540c\u6765\u6267\u884c\u4e0d\u540c\u7684\u64cd\u4f5c\u3002\u6bd4\u5982\u8003\u8651\u5982\u4e0b\u7684\u4e00\u4e2a\u8fde\u63a5\u5bf9\u8c61\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class Connection:\n    \"\"\"\u666e\u901a\u65b9\u6848\uff0c\u597d\u591a\u4e2a\u5224\u65ad\u8bed\u53e5\uff0c\u6548\u7387\u4f4e\u4e0b~~\"\"\"\n\n    def __init__(self):\n        self.state = 'CLOSED'\n\n    def read(self):\n        if self.state != 'OPEN':\n            raise RuntimeError('Not open')\n        print('reading')\n\n    def write(self, data):\n        if self.state != 'OPEN':\n            raise RuntimeError('Not open')\n        print('writing')\n\n    def open(self):\n        if self.state == 'OPEN':\n            raise RuntimeError('Already open')\n        self.state = 'OPEN'\n\n    def close(self):\n        if self.state == 'CLOSED':\n            raise RuntimeError('Already closed')\n        self.state = 'CLOSED'"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u6837\u5199\u6709\u5f88\u591a\u7f3a\u70b9\uff0c\u9996\u5148\u662f\u4ee3\u7801\u592a\u590d\u6742\u4e86\uff0c\u597d\u591a\u7684\u6761\u4ef6\u5224\u65ad\u3002\u5176\u6b21\u662f\u6267\u884c\u6548\u7387\u53d8\u4f4e\uff0c\n\u56e0\u4e3a\u4e00\u4e9b\u5e38\u89c1\u7684\u64cd\u4f5c\u6bd4\u5982read()\u3001write()\u6bcf\u6b21\u6267\u884c\u524d\u90fd\u9700\u8981\u6267\u884c\u68c0\u67e5\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e00\u4e2a\u66f4\u597d\u7684\u529e\u6cd5\u662f\u4e3a\u6bcf\u4e2a\u72b6\u6001\u5b9a\u4e49\u4e00\u4e2a\u5bf9\u8c61\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class Connection1:\n    \"\"\"\u65b0\u65b9\u6848\u2014\u2014\u5bf9\u6bcf\u4e2a\u72b6\u6001\u5b9a\u4e49\u4e00\u4e2a\u7c7b\"\"\"\n\n    def __init__(self):\n        self.new_state(ClosedConnectionState)\n\n    def new_state(self, newstate):\n        self._state = newstate\n        # Delegate to the state class\n\n    def read(self):\n        return self._state.read(self)\n\n    def write(self, data):\n        return self._state.write(self, data)\n\n    def open(self):\n        return self._state.open(self)\n\n    def close(self):\n        return self._state.close(self)\n\n\n# Connection state base class\nclass ConnectionState:\n    @staticmethod\n    def read(conn):\n        raise NotImplementedError()\n\n    @staticmethod\n    def write(conn, data):\n        raise NotImplementedError()\n\n    @staticmethod\n    def open(conn):\n        raise NotImplementedError()\n\n    @staticmethod\n    def close(conn):\n        raise NotImplementedError()\n\n\n# Implementation of different states\nclass ClosedConnectionState(ConnectionState):\n    @staticmethod\n    def read(conn):\n        raise RuntimeError('Not open')\n\n    @staticmethod\n    def write(conn, data):\n        raise RuntimeError('Not open')\n\n    @staticmethod\n    def open(conn):\n        conn.new_state(OpenConnectionState)\n\n    @staticmethod\n    def close(conn):\n        raise RuntimeError('Already closed')\n\n\nclass OpenConnectionState(ConnectionState):\n    @staticmethod\n    def read(conn):\n        print('reading')\n\n    @staticmethod\n    def write(conn, data):\n        print('writing')\n\n    @staticmethod\n    def open(conn):\n        raise RuntimeError('Already open')\n\n    @staticmethod\n    def close(conn):\n        conn.new_state(ClosedConnectionState)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e0b\u9762\u662f\u4f7f\u7528\u6f14\u793a\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "c = Connection()\nc._state"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "c.read()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "c.open()\nc._state"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "c.read()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "c.write('hello')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "c.close()\nc._state"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u4ee3\u7801\u4e2d\u51fa\u73b0\u592a\u591a\u7684\u6761\u4ef6\u5224\u65ad\u8bed\u53e5\u7684\u8bdd\uff0c\u4ee3\u7801\u5c31\u4f1a\u53d8\u5f97\u96be\u4ee5\u7ef4\u62a4\u548c\u9605\u8bfb\u3002\n\u8fd9\u91cc\u7684\u89e3\u51b3\u65b9\u6848\u662f\u5c06\u6bcf\u4e2a\u72b6\u6001\u62bd\u53d6\u51fa\u6765\u5b9a\u4e49\u6210\u4e00\u4e2a\u7c7b\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u91cc\u770b\u4e0a\u53bb\u6709\u70b9\u5947\u602a\uff0c\u6bcf\u4e2a\u72b6\u6001\u5bf9\u8c61\u90fd\u53ea\u6709\u9759\u6001\u65b9\u6cd5\uff0c\u5e76\u6ca1\u6709\u5b58\u50a8\u4efb\u4f55\u7684\u5b9e\u4f8b\u5c5e\u6027\u6570\u636e\u3002\n\u5b9e\u9645\u4e0a\uff0c\u6240\u6709\u72b6\u6001\u4fe1\u606f\u90fd\u53ea\u5b58\u50a8\u5728 Connection \u5b9e\u4f8b\u4e2d\u3002\n\u5728\u57fa\u7c7b\u4e2d\u5b9a\u4e49\u7684 NotImplementedError \u662f\u4e3a\u4e86\u786e\u4fdd\u5b50\u7c7b\u5b9e\u73b0\u4e86\u76f8\u5e94\u7684\u65b9\u6cd5\u3002\n\u8fd9\u91cc\u4f60\u6216\u8bb8\u8fd8\u60f3\u4f7f\u75288.12\u5c0f\u8282\u8bb2\u89e3\u7684\u62bd\u8c61\u57fa\u7c7b\u65b9\u5f0f\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8bbe\u8ba1\u6a21\u5f0f\u4e2d\u6709\u4e00\u79cd\u6a21\u5f0f\u53eb\u72b6\u6001\u6a21\u5f0f\uff0c\u8fd9\u4e00\u5c0f\u8282\u7b97\u662f\u4e00\u4e2a\u521d\u6b65\u5165\u95e8\uff01"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 8.20 \u901a\u8fc7\u5b57\u7b26\u4e32\u8c03\u7528\u5bf9\u8c61\u65b9\u6cd5\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u6709\u4e00\u4e2a\u5b57\u7b26\u4e32\u5f62\u5f0f\u7684\u65b9\u6cd5\u540d\u79f0\uff0c\u60f3\u901a\u8fc7\u5b83\u8c03\u7528\u67d0\u4e2a\u5bf9\u8c61\u7684\u5bf9\u5e94\u65b9\u6cd5\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u6700\u7b80\u5355\u7684\u60c5\u51b5\uff0c\u53ef\u4ee5\u4f7f\u7528 getattr() \uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import math\n\nclass Point:\n    def __init__(self, x, y):\n        self.x = x\n        self.y = y\n\n    def __repr__(self):\n        return 'Point({!r:},{!r:})'.format(self.x, self.y)\n\n    def distance(self, x, y):\n        return math.hypot(self.x - x, self.y - y)\n\n\np = Point(2, 3)\nd = getattr(p, 'distance')(0, 0)  # Calls p.distance(0, 0)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u53e6\u5916\u4e00\u79cd\u65b9\u6cd5\u662f\u4f7f\u7528 operator.methodcaller() \uff0c\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import operator\noperator.methodcaller('distance', 0, 0)(p)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5f53\u4f60\u9700\u8981\u901a\u8fc7\u76f8\u540c\u7684\u53c2\u6570\u591a\u6b21\u8c03\u7528\u67d0\u4e2a\u65b9\u6cd5\u65f6\uff0c\u4f7f\u7528 operator.methodcaller \u5c31\u5f88\u65b9\u4fbf\u4e86\u3002\n\u6bd4\u5982\u4f60\u9700\u8981\u6392\u5e8f\u4e00\u7cfb\u5217\u7684\u70b9\uff0c\u5c31\u53ef\u4ee5\u8fd9\u6837\u505a\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "points = [\n    Point(1, 2),\n    Point(3, 0),\n    Point(10, -3),\n    Point(-5, -7),\n    Point(-1, 8),\n    Point(3, 2)\n]\n# Sort by distance from origin (0, 0)\npoints.sort(key=operator.methodcaller('distance', 0, 0))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8c03\u7528\u4e00\u4e2a\u65b9\u6cd5\u5b9e\u9645\u4e0a\u662f\u4e24\u6b65\u72ec\u7acb\u64cd\u4f5c\uff0c\u7b2c\u4e00\u6b65\u662f\u67e5\u627e\u5c5e\u6027\uff0c\u7b2c\u4e8c\u6b65\u662f\u51fd\u6570\u8c03\u7528\u3002\n\u56e0\u6b64\uff0c\u4e3a\u4e86\u8c03\u7528\u67d0\u4e2a\u65b9\u6cd5\uff0c\u4f60\u53ef\u4ee5\u9996\u5148\u901a\u8fc7 getattr() \u6765\u67e5\u627e\u5230\u8fd9\u4e2a\u5c5e\u6027\uff0c\u7136\u540e\u518d\u53bb\u4ee5\u51fd\u6570\u65b9\u5f0f\u8c03\u7528\u5b83\u5373\u53ef\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "operator.methodcaller() \u521b\u5efa\u4e00\u4e2a\u53ef\u8c03\u7528\u5bf9\u8c61\uff0c\u5e76\u540c\u65f6\u63d0\u4f9b\u6240\u6709\u5fc5\u8981\u53c2\u6570\uff0c\n\u7136\u540e\u8c03\u7528\u7684\u65f6\u5019\u53ea\u9700\u8981\u5c06\u5b9e\u4f8b\u5bf9\u8c61\u4f20\u9012\u7ed9\u5b83\u5373\u53ef\uff0c\u6bd4\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "p = Point(3, 4)\nd = operator.methodcaller('distance', 0, 0)\nd(p)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u901a\u8fc7\u65b9\u6cd5\u540d\u79f0\u5b57\u7b26\u4e32\u6765\u8c03\u7528\u65b9\u6cd5\u901a\u5e38\u51fa\u73b0\u5728\u9700\u8981\u6a21\u62df case \u8bed\u53e5\u6216\u5b9e\u73b0\u8bbf\u95ee\u8005\u6a21\u5f0f\u7684\u65f6\u5019\u3002\n\u53c2\u8003\u4e0b\u4e00\u5c0f\u8282\u83b7\u53d6\u66f4\u591a\u9ad8\u7ea7\u4f8b\u5b50\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 8.21 \u5b9e\u73b0\u8bbf\u95ee\u8005\u6a21\u5f0f\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u8981\u5904\u7406\u7531\u5927\u91cf\u4e0d\u540c\u7c7b\u578b\u7684\u5bf9\u8c61\u7ec4\u6210\u7684\u590d\u6742\u6570\u636e\u7ed3\u6784\uff0c\u6bcf\u4e00\u4e2a\u5bf9\u8c61\u90fd\u9700\u8981\u8fdb\u884c\u4e0d\u540c\u7684\u5904\u7406\u3002\n\u6bd4\u5982\uff0c\u904d\u5386\u4e00\u4e2a\u6811\u5f62\u7ed3\u6784\uff0c\u7136\u540e\u6839\u636e\u6bcf\u4e2a\u8282\u70b9\u7684\u76f8\u5e94\u72b6\u6001\u6267\u884c\u4e0d\u540c\u7684\u64cd\u4f5c\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u91cc\u9047\u5230\u7684\u95ee\u9898\u5728\u7f16\u7a0b\u9886\u57df\u4e2d\u662f\u5f88\u666e\u904d\u7684\uff0c\u6709\u65f6\u5019\u4f1a\u6784\u5efa\u4e00\u4e2a\u7531\u5927\u91cf\u4e0d\u540c\u5bf9\u8c61\u7ec4\u6210\u7684\u6570\u636e\u7ed3\u6784\u3002\n\u5047\u8bbe\u4f60\u8981\u5199\u4e00\u4e2a\u8868\u793a\u6570\u5b66\u8868\u8fbe\u5f0f\u7684\u7a0b\u5e8f\uff0c\u90a3\u4e48\u4f60\u53ef\u80fd\u9700\u8981\u5b9a\u4e49\u5982\u4e0b\u7684\u7c7b\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class Node:\n    pass\n\nclass UnaryOperator(Node):\n    def __init__(self, operand):\n        self.operand = operand\n\nclass BinaryOperator(Node):\n    def __init__(self, left, right):\n        self.left = left\n        self.right = right\n\nclass Add(BinaryOperator):\n    pass\n\nclass Sub(BinaryOperator):\n    pass\n\nclass Mul(BinaryOperator):\n    pass\n\nclass Div(BinaryOperator):\n    pass\n\nclass Negate(UnaryOperator):\n    pass\n\nclass Number(Node):\n    def __init__(self, value):\n        self.value = value"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u7136\u540e\u5229\u7528\u8fd9\u4e9b\u7c7b\u6784\u5efa\u5d4c\u5957\u6570\u636e\u7ed3\u6784\uff0c\u5982\u4e0b\u6240\u793a\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# Representation of 1 + 2 * (3 - 4) / 5\nt1 = Sub(Number(3), Number(4))\nt2 = Mul(Number(2), t1)\nt3 = Div(t2, Number(5))\nt4 = Add(Number(1), t3)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u6837\u505a\u7684\u95ee\u9898\u662f\u5bf9\u4e8e\u6bcf\u4e2a\u8868\u8fbe\u5f0f\uff0c\u6bcf\u6b21\u90fd\u8981\u91cd\u65b0\u5b9a\u4e49\u4e00\u904d\uff0c\u6709\u6ca1\u6709\u4e00\u79cd\u66f4\u901a\u7528\u7684\u65b9\u5f0f\u8ba9\u5b83\u652f\u6301\u6240\u6709\u7684\u6570\u5b57\u548c\u64cd\u4f5c\u7b26\u5462\u3002\n\u8fd9\u91cc\u6211\u4eec\u4f7f\u7528\u8bbf\u95ee\u8005\u6a21\u5f0f\u53ef\u4ee5\u8fbe\u5230\u8fd9\u6837\u7684\u76ee\u7684\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class NodeVisitor:\n    def visit(self, node):\n        methname = 'visit_' + type(node).__name__\n        meth = getattr(self, methname, None)\n        if meth is None:\n            meth = self.generic_visit\n        return meth(node)\n\n    def generic_visit(self, node):\n        raise RuntimeError('No {} method'.format('visit_' + type(node).__name__))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e3a\u4e86\u4f7f\u7528\u8fd9\u4e2a\u7c7b\uff0c\u53ef\u4ee5\u5b9a\u4e49\u4e00\u4e2a\u7c7b\u7ee7\u627f\u5b83\u5e76\u4e14\u5b9e\u73b0\u5404\u79cd visit_Name() \u65b9\u6cd5\uff0c\u5176\u4e2dName\u662fnode\u7c7b\u578b\u3002\n\u4f8b\u5982\uff0c\u5982\u679c\u4f60\u60f3\u6c42\u8868\u8fbe\u5f0f\u7684\u503c\uff0c\u53ef\u4ee5\u8fd9\u6837\u5199\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class Evaluator(NodeVisitor):\n    def visit_Number(self, node):\n        return node.value\n\n    def visit_Add(self, node):\n        return self.visit(node.left) + self.visit(node.right)\n\n    def visit_Sub(self, node):\n        return self.visit(node.left) - self.visit(node.right)\n\n    def visit_Mul(self, node):\n        return self.visit(node.left) * self.visit(node.right)\n\n    def visit_Div(self, node):\n        return self.visit(node.left) / self.visit(node.right)\n\n    def visit_Negate(self, node):\n        return -node.operand"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f7f\u7528\u793a\u4f8b\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "e = Evaluator()\ne.visit(t4)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f5c\u4e3a\u4e00\u4e2a\u4e0d\u540c\u7684\u4f8b\u5b50\uff0c\u4e0b\u9762\u5b9a\u4e49\u4e00\u4e2a\u7c7b\u5728\u4e00\u4e2a\u6808\u4e0a\u9762\u5c06\u4e00\u4e2a\u8868\u8fbe\u5f0f\u8f6c\u6362\u6210\u591a\u4e2a\u64cd\u4f5c\u5e8f\u5217\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class StackCode(NodeVisitor):\n    def generate_code(self, node):\n        self.instructions = []\n        self.visit(node)\n        return self.instructions\n\n    def visit_Number(self, node):\n        self.instructions.append(('PUSH', node.value))\n\n    def binop(self, node, instruction):\n        self.visit(node.left)\n        self.visit(node.right)\n        self.instructions.append((instruction,))\n\n    def visit_Add(self, node):\n        self.binop(node, 'ADD')\n\n    def visit_Sub(self, node):\n        self.binop(node, 'SUB')\n\n    def visit_Mul(self, node):\n        self.binop(node, 'MUL')\n\n    def visit_Div(self, node):\n        self.binop(node, 'DIV')\n\n    def unaryop(self, node, instruction):\n        self.visit(node.operand)\n        self.instructions.append((instruction,))\n\n    def visit_Negate(self, node):\n        self.unaryop(node, 'NEG')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f7f\u7528\u793a\u4f8b\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "s = StackCode()\ns.generate_code(t4)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u521a\u5f00\u59cb\u7684\u65f6\u5019\u4f60\u53ef\u80fd\u4f1a\u5199\u5927\u91cf\u7684if/else\u8bed\u53e5\u6765\u5b9e\u73b0\uff0c\n\u8fd9\u91cc\u8bbf\u95ee\u8005\u6a21\u5f0f\u7684\u597d\u5904\u5c31\u662f\u901a\u8fc7 getattr() \u6765\u83b7\u53d6\u76f8\u5e94\u7684\u65b9\u6cd5\uff0c\u5e76\u5229\u7528\u9012\u5f52\u6765\u904d\u5386\u6240\u6709\u7684\u8282\u70b9\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "def binop(self, node, instruction):\n    self.visit(node.left)\n    self.visit(node.right)\n    self.instructions.append((instruction,))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd8\u6709\u4e00\u70b9\u9700\u8981\u6307\u51fa\u7684\u662f\uff0c\u8fd9\u79cd\u6280\u672f\u4e5f\u662f\u5b9e\u73b0\u5176\u4ed6\u8bed\u8a00\u4e2dswitch\u6216case\u8bed\u53e5\u7684\u65b9\u5f0f\u3002\n\u6bd4\u5982\uff0c\u5982\u679c\u4f60\u6b63\u5728\u5199\u4e00\u4e2aHTTP\u6846\u67b6\uff0c\u4f60\u53ef\u80fd\u4f1a\u5199\u8fd9\u6837\u4e00\u4e2a\u8bf7\u6c42\u5206\u53d1\u7684\u63a7\u5236\u5668\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class HTTPHandler:\n    def handle(self, request):\n        methname = 'do_' + request.request_method\n        getattr(self, methname)(request)\n    def do_GET(self, request):\n        pass\n    def do_POST(self, request):\n        pass\n    def do_HEAD(self, request):\n        pass"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8bbf\u95ee\u8005\u6a21\u5f0f\u4e00\u4e2a\u7f3a\u70b9\u5c31\u662f\u5b83\u4e25\u91cd\u4f9d\u8d56\u9012\u5f52\uff0c\u5982\u679c\u6570\u636e\u7ed3\u6784\u5d4c\u5957\u5c42\u6b21\u592a\u6df1\u53ef\u80fd\u4f1a\u6709\u95ee\u9898\uff0c\n\u6709\u65f6\u5019\u4f1a\u8d85\u8fc7Python\u7684\u9012\u5f52\u6df1\u5ea6\u9650\u5236(\u53c2\u8003 sys.getrecursionlimit() )\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u53ef\u4ee5\u53c2\u71678.22\u5c0f\u8282\uff0c\u5229\u7528\u751f\u6210\u5668\u6216\u8fed\u4ee3\u5668\u6765\u5b9e\u73b0\u975e\u9012\u5f52\u904d\u5386\u7b97\u6cd5\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5728\u8ddf\u89e3\u6790\u548c\u7f16\u8bd1\u76f8\u5173\u7684\u7f16\u7a0b\u4e2d\u4f7f\u7528\u8bbf\u95ee\u8005\u6a21\u5f0f\u662f\u975e\u5e38\u5e38\u89c1\u7684\u3002\nPython\u672c\u8eab\u7684 ast \u6a21\u5757\u503c\u5f97\u5173\u6ce8\u4e0b\uff0c\u53ef\u4ee5\u53bb\u770b\u770b\u6e90\u7801\u3002\n9.24\u5c0f\u8282\u6f14\u793a\u4e86\u4e00\u4e2a\u5229\u7528 ast \u6a21\u5757\u6765\u5904\u7406Python\u6e90\u4ee3\u7801\u7684\u4f8b\u5b50\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 8.22 \u4e0d\u7528\u9012\u5f52\u5b9e\u73b0\u8bbf\u95ee\u8005\u6a21\u5f0f\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u4f7f\u7528\u8bbf\u95ee\u8005\u6a21\u5f0f\u904d\u5386\u4e00\u4e2a\u5f88\u6df1\u7684\u5d4c\u5957\u6811\u5f62\u6570\u636e\u7ed3\u6784\uff0c\u5e76\u4e14\u56e0\u4e3a\u8d85\u8fc7\u5d4c\u5957\u5c42\u7ea7\u9650\u5236\u800c\u5931\u8d25\u3002\n\u4f60\u60f3\u6d88\u9664\u9012\u5f52\uff0c\u5e76\u540c\u65f6\u4fdd\u6301\u8bbf\u95ee\u8005\u7f16\u7a0b\u6a21\u5f0f\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u901a\u8fc7\u5de7\u5999\u7684\u4f7f\u7528\u751f\u6210\u5668\u53ef\u4ee5\u5728\u6811\u904d\u5386\u6216\u641c\u7d22\u7b97\u6cd5\u4e2d\u6d88\u9664\u9012\u5f52\u3002\n\u57288.21\u5c0f\u8282\u4e2d\uff0c\u6211\u4eec\u7ed9\u51fa\u4e86\u4e00\u4e2a\u8bbf\u95ee\u8005\u7c7b\u3002\n\u4e0b\u9762\u6211\u4eec\u5229\u7528\u4e00\u4e2a\u6808\u548c\u751f\u6210\u5668\u91cd\u65b0\u5b9e\u73b0\u8fd9\u4e2a\u7c7b\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import types\n\nclass Node:\n    pass\n\nclass NodeVisitor:\n    def visit(self, node):\n        stack = [node]\n        last_result = None\n        while stack:\n            try:\n                last = stack[-1]\n                if isinstance(last, types.GeneratorType):\n                    stack.append(last.send(last_result))\n                    last_result = None\n                elif isinstance(last, Node):\n                    stack.append(self._visit(stack.pop()))\n                else:\n                    last_result = stack.pop()\n            except StopIteration:\n                stack.pop()\n\n        return last_result\n\n    def _visit(self, node):\n        methname = 'visit_' + type(node).__name__\n        meth = getattr(self, methname, None)\n        if meth is None:\n            meth = self.generic_visit\n        return meth(node)\n\n    def generic_visit(self, node):\n        raise RuntimeError('No {} method'.format('visit_' + type(node).__name__))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u4f60\u4f7f\u7528\u8fd9\u4e2a\u7c7b\uff0c\u4e5f\u80fd\u8fbe\u5230\u76f8\u540c\u7684\u6548\u679c\u3002\u4e8b\u5b9e\u4e0a\u4f60\u5b8c\u5168\u53ef\u4ee5\u5c06\u5b83\u4f5c\u4e3a\u4e0a\u4e00\u8282\u4e2d\u7684\u8bbf\u95ee\u8005\u6a21\u5f0f\u7684\u66ff\u4ee3\u5b9e\u73b0\u3002\n\u8003\u8651\u5982\u4e0b\u4ee3\u7801\uff0c\u904d\u5386\u4e00\u4e2a\u8868\u8fbe\u5f0f\u7684\u6811\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class UnaryOperator(Node):\n    def __init__(self, operand):\n        self.operand = operand\n\nclass BinaryOperator(Node):\n    def __init__(self, left, right):\n        self.left = left\n        self.right = right\n\nclass Add(BinaryOperator):\n    pass\n\nclass Sub(BinaryOperator):\n    pass\n\nclass Mul(BinaryOperator):\n    pass\n\nclass Div(BinaryOperator):\n    pass\n\nclass Negate(UnaryOperator):\n    pass\n\nclass Number(Node):\n    def __init__(self, value):\n        self.value = value\n\n# A sample visitor class that evaluates expressions\nclass Evaluator(NodeVisitor):\n    def visit_Number(self, node):\n        return node.value\n\n    def visit_Add(self, node):\n        return self.visit(node.left) + self.visit(node.right)\n\n    def visit_Sub(self, node):\n        return self.visit(node.left) - self.visit(node.right)\n\n    def visit_Mul(self, node):\n        return self.visit(node.left) * self.visit(node.right)\n\n    def visit_Div(self, node):\n        return self.visit(node.left) / self.visit(node.right)\n\n    def visit_Negate(self, node):\n        return -self.visit(node.operand)\n\nif __name__ == '__main__':\n    # 1 + 2*(3-4) / 5\n    t1 = Sub(Number(3), Number(4))\n    t2 = Mul(Number(2), t1)\n    t3 = Div(t2, Number(5))\n    t4 = Add(Number(1), t3)\n    # Evaluate it\n    e = Evaluator()\n    print(e.visit(t4))  # Outputs 0.6"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u5d4c\u5957\u5c42\u6b21\u592a\u6df1\u90a3\u4e48\u4e0a\u8ff0\u7684Evaluator\u5c31\u4f1a\u5931\u6548\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "a = Number(0)\nfor n in range(1, 100000):\na = Add(a, Number(n))\ne = Evaluator()\ne.visit(a)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u73b0\u5728\u6211\u4eec\u7a0d\u5fae\u4fee\u6539\u4e0b\u4e0a\u9762\u7684Evaluator\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class Evaluator(NodeVisitor):\n    def visit_Number(self, node):\n        return node.value\n\n    def visit_Add(self, node):\n        yield (yield node.left) + (yield node.right)\n\n    def visit_Sub(self, node):\n        yield (yield node.left) - (yield node.right)\n\n    def visit_Mul(self, node):\n        yield (yield node.left) * (yield node.right)\n\n    def visit_Div(self, node):\n        yield (yield node.left) / (yield node.right)\n\n    def visit_Negate(self, node):\n        yield - (yield node.operand)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u518d\u6b21\u8fd0\u884c\uff0c\u5c31\u4e0d\u4f1a\u62a5\u9519\u4e86\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "a = Number(0)\nfor n in range(1,100000):\n    a = Add(a, Number(n))\ne = Evaluator()\ne.visit(a)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u4f60\u8fd8\u60f3\u6dfb\u52a0\u5176\u4ed6\u81ea\u5b9a\u4e49\u903b\u8f91\u4e5f\u6ca1\u95ee\u9898\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class Evaluator(NodeVisitor):\n    ...\n    def visit_Add(self, node):\n        print('Add:', node)\n        lhs = yield node.left\n        print('left=', lhs)\n        rhs = yield node.right\n        print('right=', rhs)\n        yield lhs + rhs\n    ..."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e0b\u9762\u662f\u7b80\u5355\u7684\u6d4b\u8bd5\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "e = Evaluator()\ne.visit(t4)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u4e00\u5c0f\u8282\u6211\u4eec\u6f14\u793a\u4e86\u751f\u6210\u5668\u548c\u534f\u7a0b\u5728\u7a0b\u5e8f\u63a7\u5236\u6d41\u65b9\u9762\u7684\u5f3a\u5927\u529f\u80fd\u3002\n\u907f\u514d\u9012\u5f52\u7684\u4e00\u4e2a\u901a\u5e38\u65b9\u6cd5\u662f\u4f7f\u7528\u4e00\u4e2a\u6808\u6216\u961f\u5217\u7684\u6570\u636e\u7ed3\u6784\u3002\n\u4f8b\u5982\uff0c\u6df1\u5ea6\u4f18\u5148\u7684\u904d\u5386\u7b97\u6cd5\uff0c\u7b2c\u4e00\u6b21\u78b0\u5230\u4e00\u4e2a\u8282\u70b9\u65f6\u5c06\u5176\u538b\u5165\u6808\u4e2d\uff0c\u5904\u7406\u5b8c\u540e\u5f39\u51fa\u6808\u3002visit() \u65b9\u6cd5\u7684\u6838\u5fc3\u601d\u8def\u5c31\u662f\u8fd9\u6837\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u53e6\u5916\u4e00\u4e2a\u9700\u8981\u7406\u89e3\u7684\u5c31\u662f\u751f\u6210\u5668\u4e2dyield\u8bed\u53e5\u3002\u5f53\u78b0\u5230yield\u8bed\u53e5\u65f6\uff0c\u751f\u6210\u5668\u4f1a\u8fd4\u56de\u4e00\u4e2a\u6570\u636e\u5e76\u6682\u65f6\u6302\u8d77\u3002\n\u4e0a\u9762\u7684\u4f8b\u5b50\u4f7f\u7528\u8fd9\u4e2a\u6280\u672f\u6765\u4ee3\u66ff\u4e86\u9012\u5f52\u3002\u4f8b\u5982\uff0c\u4e4b\u524d\u6211\u4eec\u662f\u8fd9\u6837\u5199\u9012\u5f52\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "value = self.visit(node.left)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u73b0\u5728\u6362\u6210yield\u8bed\u53e5\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "value = yield node.left"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5b83\u4f1a\u5c06 node.left \u8fd4\u56de\u7ed9 visit() \u65b9\u6cd5\uff0c\u7136\u540e visit() \u65b9\u6cd5\u8c03\u7528\u90a3\u4e2a\u8282\u70b9\u76f8\u5e94\u7684 visit_Name() \u65b9\u6cd5\u3002\nyield\u6682\u65f6\u5c06\u7a0b\u5e8f\u63a7\u5236\u5668\u8ba9\u51fa\u7ed9\u8c03\u7528\u8005\uff0c\u5f53\u6267\u884c\u5b8c\u540e\uff0c\u7ed3\u679c\u4f1a\u8d4b\u503c\u7ed9value\uff0c"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u770b\u5b8c\u8fd9\u4e00\u5c0f\u8282\uff0c\u4f60\u4e5f\u8bb8\u60f3\u53bb\u5bfb\u627e\u5176\u5b83\u6ca1\u6709yield\u8bed\u53e5\u7684\u65b9\u6848\u3002\u4f46\u662f\u8fd9\u4e48\u505a\u6ca1\u6709\u5fc5\u8981\uff0c\u4f60\u5fc5\u987b\u5904\u7406\u5f88\u591a\u68d8\u624b\u7684\u95ee\u9898\u3002\n\u4f8b\u5982\uff0c\u4e3a\u4e86\u6d88\u9664\u9012\u5f52\uff0c\u4f60\u5fc5\u987b\u8981\u7ef4\u62a4\u4e00\u4e2a\u6808\u7ed3\u6784\uff0c\u5982\u679c\u4e0d\u4f7f\u7528\u751f\u6210\u5668\uff0c\u4ee3\u7801\u4f1a\u53d8\u5f97\u5f88\u81c3\u80bf\uff0c\u5230\u5904\u90fd\u662f\u6808\u64cd\u4f5c\u8bed\u53e5\u3001\u56de\u8c03\u51fd\u6570\u7b49\u3002\n\u5b9e\u9645\u4e0a\uff0c\u4f7f\u7528yield\u8bed\u53e5\u53ef\u4ee5\u8ba9\u4f60\u5199\u51fa\u975e\u5e38\u6f02\u4eae\u7684\u4ee3\u7801\uff0c\u5b83\u6d88\u9664\u4e86\u9012\u5f52\u4f46\u662f\u770b\u4e0a\u53bb\u53c8\u5f88\u50cf\u9012\u5f52\u5b9e\u73b0\uff0c\u4ee3\u7801\u5f88\u7b80\u6d01\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 8.23 \u5faa\u73af\u5f15\u7528\u6570\u636e\u7ed3\u6784\u7684\u5185\u5b58\u7ba1\u7406\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u7684\u7a0b\u5e8f\u521b\u5efa\u4e86\u5f88\u591a\u5faa\u73af\u5f15\u7528\u6570\u636e\u7ed3\u6784(\u6bd4\u5982\u6811\u3001\u56fe\u3001\u89c2\u5bdf\u8005\u6a21\u5f0f\u7b49)\uff0c\u4f60\u78b0\u5230\u4e86\u5185\u5b58\u7ba1\u7406\u96be\u9898\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e00\u4e2a\u7b80\u5355\u7684\u5faa\u73af\u5f15\u7528\u6570\u636e\u7ed3\u6784\u4f8b\u5b50\u5c31\u662f\u4e00\u4e2a\u6811\u5f62\u7ed3\u6784\uff0c\u53cc\u4eb2\u8282\u70b9\u6709\u6307\u9488\u6307\u5411\u5b69\u5b50\u8282\u70b9\uff0c\u5b69\u5b50\u8282\u70b9\u53c8\u8fd4\u56de\u6765\u6307\u5411\u53cc\u4eb2\u8282\u70b9\u3002\n\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u53ef\u4ee5\u8003\u8651\u4f7f\u7528 weakref \u5e93\u4e2d\u7684\u5f31\u5f15\u7528\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import weakref\n\nclass Node:\n    def __init__(self, value):\n        self.value = value\n        self._parent = None\n        self.children = []\n\n    def __repr__(self):\n        return 'Node({!r:})'.format(self.value)\n\n    # property that manages the parent as a weak-reference\n    @property\n    def parent(self):\n        return None if self._parent is None else self._parent()\n\n    @parent.setter\n    def parent(self, node):\n        self._parent = weakref.ref(node)\n\n    def add_child(self, child):\n        self.children.append(child)\n        child.parent = self"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u79cd\u662f\u60f3\u65b9\u5f0f\u5141\u8bb8parent\u9759\u9ed8\u7ec8\u6b62\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "root = Node('parent')\nc1 = Node('child')\nroot.add_child(c1)\nprint(c1.parent)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "del root\nprint(c1.parent)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5faa\u73af\u5f15\u7528\u7684\u6570\u636e\u7ed3\u6784\u5728Python\u4e2d\u662f\u4e00\u4e2a\u5f88\u68d8\u624b\u7684\u95ee\u9898\uff0c\u56e0\u4e3a\u6b63\u5e38\u7684\u5783\u573e\u56de\u6536\u673a\u5236\u4e0d\u80fd\u9002\u7528\u4e8e\u8fd9\u79cd\u60c5\u5f62\u3002\n\u4f8b\u5982\u8003\u8651\u5982\u4e0b\u4ee3\u7801\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# Class just to illustrate when deletion occurs\nclass Data:\n    def __del__(self):\n        print('Data.__del__')\n\n# Node class involving a cycle\nclass Node:\n    def __init__(self):\n        self.data = Data()\n        self.parent = None\n        self.children = []\n\n    def add_child(self, child):\n        self.children.append(child)\n        child.parent = self"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e0b\u9762\u6211\u4eec\u4f7f\u7528\u8fd9\u4e2a\u4ee3\u7801\u6765\u505a\u4e00\u4e9b\u5783\u573e\u56de\u6536\u8bd5\u9a8c\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "a = Data()\ndel a # Immediately deleted"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "a = Node()\ndel a # Immediately deleted"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "a = Node()\na.add_child(Node())\ndel a # Not deleted (no message)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u53ef\u4ee5\u770b\u5230\uff0c\u6700\u540e\u4e00\u4e2a\u7684\u5220\u9664\u65f6\u6253\u5370\u8bed\u53e5\u6ca1\u6709\u51fa\u73b0\u3002\u539f\u56e0\u662fPython\u7684\u5783\u573e\u56de\u6536\u673a\u5236\u662f\u57fa\u4e8e\u7b80\u5355\u7684\u5f15\u7528\u8ba1\u6570\u3002\n\u5f53\u4e00\u4e2a\u5bf9\u8c61\u7684\u5f15\u7528\u6570\u53d8\u62100\u7684\u65f6\u5019\u624d\u4f1a\u7acb\u5373\u5220\u9664\u6389\u3002\u800c\u5bf9\u4e8e\u5faa\u73af\u5f15\u7528\u8fd9\u4e2a\u6761\u4ef6\u6c38\u8fdc\u4e0d\u4f1a\u6210\u7acb\u3002\n\u56e0\u6b64\uff0c\u5728\u4e0a\u9762\u4f8b\u5b50\u4e2d\u6700\u540e\u90e8\u5206\uff0c\u7236\u8282\u70b9\u548c\u5b69\u5b50\u8282\u70b9\u4e92\u76f8\u62e5\u6709\u5bf9\u65b9\u7684\u5f15\u7528\uff0c\u5bfc\u81f4\u6bcf\u4e2a\u5bf9\u8c61\u7684\u5f15\u7528\u8ba1\u6570\u90fd\u4e0d\u53ef\u80fd\u53d8\u62100\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Python\u6709\u53e6\u5916\u7684\u5783\u573e\u56de\u6536\u5668\u6765\u4e13\u95e8\u9488\u5bf9\u5faa\u73af\u5f15\u7528\u7684\uff0c\u4f46\u662f\u4f60\u6c38\u8fdc\u4e0d\u77e5\u9053\u5b83\u4ec0\u4e48\u65f6\u5019\u4f1a\u89e6\u53d1\u3002\n\u53e6\u5916\u4f60\u8fd8\u53ef\u4ee5\u624b\u52a8\u7684\u89e6\u53d1\u5b83\uff0c\u4f46\u662f\u4ee3\u7801\u770b\u4e0a\u53bb\u5f88\u632b\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import gc\ngc.collect() # Force collection"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5982\u679c\u5faa\u73af\u5f15\u7528\u7684\u5bf9\u8c61\u81ea\u5df1\u8fd8\u5b9a\u4e49\u4e86\u81ea\u5df1\u7684 __del__() \u65b9\u6cd5\uff0c\u90a3\u4e48\u4f1a\u8ba9\u60c5\u51b5\u53d8\u5f97\u66f4\u7cdf\u7cd5\u3002\n\u5047\u8bbe\u4f60\u50cf\u4e0b\u9762\u8fd9\u6837\u7ed9Node\u5b9a\u4e49\u81ea\u5df1\u7684 __del__() \u65b9\u6cd5\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# Node class involving a cycle\nclass Node:\n    def __init__(self):\n        self.data = Data()\n        self.parent = None\n        self.children = []\n\n    def add_child(self, child):\n        self.children.append(child)\n        child.parent = self\n\n    # NEVER DEFINE LIKE THIS.\n    # Only here to illustrate pathological behavior\n    def __del__(self):\n        del self.data\n        del.parent\n        del.children"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u5783\u573e\u56de\u6536\u6c38\u8fdc\u90fd\u4e0d\u4f1a\u53bb\u56de\u6536\u8fd9\u4e2a\u5bf9\u8c61\u7684\uff0c\u8fd8\u4f1a\u5bfc\u81f4\u5185\u5b58\u6cc4\u9732\u3002\n\u5982\u679c\u4f60\u8bd5\u7740\u53bb\u8fd0\u884c\u5b83\u4f1a\u53d1\u73b0\uff0cData.__del__ \u6d88\u606f\u6c38\u8fdc\u4e0d\u4f1a\u51fa\u73b0\u4e86,\u751a\u81f3\u5728\u4f60\u5f3a\u5236\u5185\u5b58\u56de\u6536\u65f6\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "a = Node()\na.add_child(Node()\ndel a # No message (not collected)\nimport gc\ngc.collect() # No message (not collected)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5f31\u5f15\u7528\u6d88\u9664\u4e86\u5f15\u7528\u5faa\u73af\u7684\u8fd9\u4e2a\u95ee\u9898\uff0c\u672c\u8d28\u6765\u8bb2\uff0c\u5f31\u5f15\u7528\u5c31\u662f\u4e00\u4e2a\u5bf9\u8c61\u6307\u9488\uff0c\u5b83\u4e0d\u4f1a\u589e\u52a0\u5b83\u7684\u5f15\u7528\u8ba1\u6570\u3002\n\u4f60\u53ef\u4ee5\u901a\u8fc7 weakref \u6765\u521b\u5efa\u5f31\u5f15\u7528\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import weakref\na = Node()\na_ref = weakref.ref(a)\na_ref"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e3a\u4e86\u8bbf\u95ee\u5f31\u5f15\u7528\u6240\u5f15\u7528\u7684\u5bf9\u8c61\uff0c\u4f60\u53ef\u4ee5\u50cf\u51fd\u6570\u4e00\u6837\u53bb\u8c03\u7528\u5b83\u5373\u53ef\u3002\u5982\u679c\u90a3\u4e2a\u5bf9\u8c61\u8fd8\u5b58\u5728\u5c31\u4f1a\u8fd4\u56de\u5b83\uff0c\u5426\u5219\u5c31\u8fd4\u56de\u4e00\u4e2aNone\u3002\n\u7531\u4e8e\u539f\u59cb\u5bf9\u8c61\u7684\u5f15\u7528\u8ba1\u6570\u6ca1\u6709\u589e\u52a0\uff0c\u90a3\u4e48\u5c31\u53ef\u4ee5\u53bb\u5220\u9664\u5b83\u4e86\u3002\u4f8b\u5982;"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "print(a_ref())"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "del a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "print(a_ref())"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u901a\u8fc7\u8fd9\u91cc\u6f14\u793a\u7684\u5f31\u5f15\u7528\u6280\u672f\uff0c\u4f60\u4f1a\u53d1\u73b0\u4e0d\u518d\u6709\u5faa\u73af\u5f15\u7528\u95ee\u9898\u4e86\uff0c\u4e00\u65e6\u67d0\u4e2a\u8282\u70b9\u4e0d\u88ab\u4f7f\u7528\u4e86\uff0c\u5783\u573e\u56de\u6536\u5668\u7acb\u5373\u56de\u6536\u5b83\u3002\n\u4f60\u8fd8\u80fd\u53c2\u80038.25\u5c0f\u8282\u5173\u4e8e\u5f31\u5f15\u7528\u7684\u53e6\u5916\u4e00\u4e2a\u4f8b\u5b50\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 8.24 \u8ba9\u7c7b\u652f\u6301\u6bd4\u8f83\u64cd\u4f5c\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f60\u60f3\u8ba9\u67d0\u4e2a\u7c7b\u7684\u5b9e\u4f8b\u652f\u6301\u6807\u51c6\u7684\u6bd4\u8f83\u8fd0\u7b97(\u6bd4\u5982>=,!=,<=,<\u7b49)\uff0c\u4f46\u662f\u53c8\u4e0d\u60f3\u53bb\u5b9e\u73b0\u90a3\u4e00\u5927\u4e22\u7684\u7279\u6b8a\u65b9\u6cd5\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Python\u7c7b\u5bf9\u6bcf\u4e2a\u6bd4\u8f83\u64cd\u4f5c\u90fd\u9700\u8981\u5b9e\u73b0\u4e00\u4e2a\u7279\u6b8a\u65b9\u6cd5\u6765\u652f\u6301\u3002\n\u4f8b\u5982\u4e3a\u4e86\u652f\u6301>=\u64cd\u4f5c\u7b26\uff0c\u4f60\u9700\u8981\u5b9a\u4e49\u4e00\u4e2a __ge__() \u65b9\u6cd5\u3002\n\u5c3d\u7ba1\u5b9a\u4e49\u4e00\u4e2a\u65b9\u6cd5\u6ca1\u4ec0\u4e48\u95ee\u9898\uff0c\u4f46\u5982\u679c\u8981\u4f60\u5b9e\u73b0\u6240\u6709\u53ef\u80fd\u7684\u6bd4\u8f83\u65b9\u6cd5\u90a3\u5c31\u6709\u70b9\u70e6\u4eba\u4e86\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u88c5\u9970\u5668 functools.total_ordering \u5c31\u662f\u7528\u6765\u7b80\u5316\u8fd9\u4e2a\u5904\u7406\u7684\u3002\n\u4f7f\u7528\u5b83\u6765\u88c5\u9970\u4e00\u4e2a\u7c7b\uff0c\u4f60\u53ea\u9700\u5b9a\u4e49\u4e00\u4e2a __eq__() \u65b9\u6cd5\uff0c\n\u5916\u52a0\u5176\u4ed6\u65b9\u6cd5(__lt__, __le__, __gt__, or __ge__)\u4e2d\u7684\u4e00\u4e2a\u5373\u53ef\u3002\n\u7136\u540e\u88c5\u9970\u5668\u4f1a\u81ea\u52a8\u4e3a\u4f60\u586b\u5145\u5176\u5b83\u6bd4\u8f83\u65b9\u6cd5\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f5c\u4e3a\u4f8b\u5b50\uff0c\u6211\u4eec\u6784\u5efa\u4e00\u4e9b\u623f\u5b50\uff0c\u7136\u540e\u7ed9\u5b83\u4eec\u589e\u52a0\u4e00\u4e9b\u623f\u95f4\uff0c\u6700\u540e\u901a\u8fc7\u623f\u5b50\u5927\u5c0f\u6765\u6bd4\u8f83\u5b83\u4eec\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "from functools import total_ordering\n\nclass Room:\n    def __init__(self, name, length, width):\n        self.name = name\n        self.length = length\n        self.width = width\n        self.square_feet = self.length * self.width\n\n@total_ordering\nclass House:\n    def __init__(self, name, style):\n        self.name = name\n        self.style = style\n        self.rooms = list()\n\n    @property\n    def living_space_footage(self):\n        return sum(r.square_feet for r in self.rooms)\n\n    def add_room(self, room):\n        self.rooms.append(room)\n\n    def __str__(self):\n        return '{}: {} square foot {}'.format(self.name,\n                self.living_space_footage,\n                self.style)\n\n    def __eq__(self, other):\n        return self.living_space_footage == other.living_space_footage\n\n    def __lt__(self, other):\n        return self.living_space_footage < other.living_space_footage"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u91cc\u6211\u4eec\u53ea\u662f\u7ed9House\u7c7b\u5b9a\u4e49\u4e86\u4e24\u4e2a\u65b9\u6cd5\uff1a__eq__() \u548c __lt__() \uff0c\u5b83\u5c31\u80fd\u652f\u6301\u6240\u6709\u7684\u6bd4\u8f83\u64cd\u4f5c\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# Build a few houses, and add rooms to them\nh1 = House('h1', 'Cape')\nh1.add_room(Room('Master Bedroom', 14, 21))\nh1.add_room(Room('Living Room', 18, 20))\nh1.add_room(Room('Kitchen', 12, 16))\nh1.add_room(Room('Office', 12, 12))\nh2 = House('h2', 'Ranch')\nh2.add_room(Room('Master Bedroom', 14, 21))\nh2.add_room(Room('Living Room', 18, 20))\nh2.add_room(Room('Kitchen', 12, 16))\nh3 = House('h3', 'Split')\nh3.add_room(Room('Master Bedroom', 14, 21))\nh3.add_room(Room('Living Room', 18, 20))\nh3.add_room(Room('Office', 12, 16))\nh3.add_room(Room('Kitchen', 15, 17))\nhouses = [h1, h2, h3]\nprint('Is h1 bigger than h2?', h1 > h2) # prints True\nprint('Is h2 smaller than h3?', h2 < h3) # prints True\nprint('Is h2 greater than or equal to h1?', h2 >= h1) # Prints False\nprint('Which one is biggest?', max(houses)) # Prints 'h3: 1101-square-foot Split'\nprint('Which is smallest?', min(houses)) # Prints 'h2: 846-square-foot Ranch'"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5176\u5b9e total_ordering \u88c5\u9970\u5668\u4e5f\u6ca1\u90a3\u4e48\u795e\u79d8\u3002\n\u5b83\u5c31\u662f\u5b9a\u4e49\u4e86\u4e00\u4e2a\u4ece\u6bcf\u4e2a\u6bd4\u8f83\u652f\u6301\u65b9\u6cd5\u5230\u6240\u6709\u9700\u8981\u5b9a\u4e49\u7684\u5176\u4ed6\u65b9\u6cd5\u7684\u4e00\u4e2a\u6620\u5c04\u800c\u5df2\u3002\n\u6bd4\u5982\u4f60\u5b9a\u4e49\u4e86 __le__() \u65b9\u6cd5\uff0c\u90a3\u4e48\u5b83\u5c31\u88ab\u7528\u6765\u6784\u5efa\u6240\u6709\u5176\u4ed6\u7684\u9700\u8981\u5b9a\u4e49\u7684\u90a3\u4e9b\u7279\u6b8a\u65b9\u6cd5\u3002\n\u5b9e\u9645\u4e0a\u5c31\u662f\u5728\u7c7b\u91cc\u9762\u50cf\u4e0b\u9762\u8fd9\u6837\u5b9a\u4e49\u4e86\u4e00\u4e9b\u7279\u6b8a\u65b9\u6cd5\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class House:\n    def __eq__(self, other):\n        pass\n    def __lt__(self, other):\n        pass\n    # Methods created by @total_ordering\n    __le__ = lambda self, other: self < other or self == other\n    __gt__ = lambda self, other: not (self < other or self == other)\n    __ge__ = lambda self, other: not (self < other)\n    __ne__ = lambda self, other: not self == other"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5f53\u7136\uff0c\u4f60\u81ea\u5df1\u53bb\u5199\u4e5f\u5f88\u5bb9\u6613\uff0c\u4f46\u662f\u4f7f\u7528 @total_ordering \u53ef\u4ee5\u7b80\u5316\u4ee3\u7801\uff0c\u4f55\u4e50\u800c\u4e0d\u4e3a\u5462\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 8.25 \u521b\u5efa\u7f13\u5b58\u5b9e\u4f8b\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u95ee\u9898\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5728\u521b\u5efa\u4e00\u4e2a\u7c7b\u7684\u5bf9\u8c61\u65f6\uff0c\u5982\u679c\u4e4b\u524d\u4f7f\u7528\u540c\u6837\u53c2\u6570\u521b\u5efa\u8fc7\u8fd9\u4e2a\u5bf9\u8c61\uff0c \u4f60\u60f3\u8fd4\u56de\u5b83\u7684\u7f13\u5b58\u5f15\u7528\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u89e3\u51b3\u65b9\u6848\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u79cd\u901a\u5e38\u662f\u56e0\u4e3a\u4f60\u5e0c\u671b\u76f8\u540c\u53c2\u6570\u521b\u5efa\u7684\u5bf9\u8c61\u65f6\u5355\u4f8b\u7684\u3002\n\u5728\u5f88\u591a\u5e93\u4e2d\u90fd\u6709\u5b9e\u9645\u7684\u4f8b\u5b50\uff0c\u6bd4\u5982 logging \u6a21\u5757\uff0c\u4f7f\u7528\u76f8\u540c\u7684\u540d\u79f0\u521b\u5efa\u7684 logger \u5b9e\u4f8b\u6c38\u8fdc\u53ea\u6709\u4e00\u4e2a\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import logging\na = logging.getLogger('foo')\nb = logging.getLogger('bar')\na is b"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "c = logging.getLogger('foo')\na is c"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e3a\u4e86\u8fbe\u5230\u8fd9\u6837\u7684\u6548\u679c\uff0c\u4f60\u9700\u8981\u4f7f\u7528\u4e00\u4e2a\u548c\u7c7b\u672c\u8eab\u5206\u5f00\u7684\u5de5\u5382\u51fd\u6570\uff0c\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# The class in question\nclass Spam:\n    def __init__(self, name):\n        self.name = name\n\n# Caching support\nimport weakref\n_spam_cache = weakref.WeakValueDictionary()\ndef get_spam(name):\n    if name not in _spam_cache:\n        s = Spam(name)\n        _spam_cache[name] = s\n    else:\n        s = _spam_cache[name]\n    return s"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u7136\u540e\u505a\u4e00\u4e2a\u6d4b\u8bd5\uff0c\u4f60\u4f1a\u53d1\u73b0\u8ddf\u4e4b\u524d\u90a3\u4e2a\u65e5\u5fd7\u5bf9\u8c61\u7684\u521b\u5efa\u884c\u4e3a\u662f\u4e00\u81f4\u7684\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "a = get_spam('foo')\nb = get_spam('bar')\na is b"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "c = get_spam('foo')\na is c"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### \u8ba8\u8bba\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u7f16\u5199\u4e00\u4e2a\u5de5\u5382\u51fd\u6570\u6765\u4fee\u6539\u666e\u901a\u7684\u5b9e\u4f8b\u521b\u5efa\u884c\u4e3a\u901a\u5e38\u662f\u4e00\u4e2a\u6bd4\u8f83\u7b80\u5355\u7684\u65b9\u6cd5\u3002\n\u4f46\u662f\u6211\u4eec\u8fd8\u80fd\u5426\u627e\u5230\u66f4\u4f18\u96c5\u7684\u89e3\u51b3\u65b9\u6848\u5462\uff1f"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4f8b\u5982\uff0c\u4f60\u53ef\u80fd\u4f1a\u8003\u8651\u91cd\u65b0\u5b9a\u4e49\u7c7b\u7684 __new__() \u65b9\u6cd5\uff0c\u5c31\u50cf\u4e0b\u9762\u8fd9\u6837\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# Note: This code doesn't quite work\nimport weakref\n\nclass Spam:\n    _spam_cache = weakref.WeakValueDictionary()\n    def __new__(cls, name):\n        if name in cls._spam_cache:\n            return cls._spam_cache[name]\n        else:\n            self = super().__new__(cls)\n            cls._spam_cache[name] = self\n            return self\n    def __init__(self, name):\n        print('Initializing Spam')\n        self.name = name"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u521d\u770b\u8d77\u6765\u597d\u50cf\u53ef\u4ee5\u8fbe\u5230\u9884\u671f\u6548\u679c\uff0c\u4f46\u662f\u95ee\u9898\u662f __init__() \u6bcf\u6b21\u90fd\u4f1a\u88ab\u8c03\u7528\uff0c\u4e0d\u7ba1\u8fd9\u4e2a\u5b9e\u4f8b\u662f\u5426\u88ab\u7f13\u5b58\u4e86\u3002\u4f8b\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "s = Spam('Dave')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "t = Spam('Dave')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "s is t"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u4e2a\u6216\u8bb8\u4e0d\u662f\u4f60\u60f3\u8981\u7684\u6548\u679c\uff0c\u56e0\u6b64\u8fd9\u79cd\u65b9\u6cd5\u5e76\u4e0d\u53ef\u53d6\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u4e0a\u9762\u6211\u4eec\u4f7f\u7528\u5230\u4e86\u5f31\u5f15\u7528\u8ba1\u6570\uff0c\u5bf9\u4e8e\u5783\u573e\u56de\u6536\u6765\u8bb2\u662f\u5f88\u6709\u5e2e\u52a9\u7684\uff0c\u5173\u4e8e\u8fd9\u4e2a\u6211\u4eec\u57288.23\u5c0f\u8282\u5df2\u7ecf\u8bb2\u8fc7\u4e86\u3002\n\u5f53\u6211\u4eec\u4fdd\u6301\u5b9e\u4f8b\u7f13\u5b58\u65f6\uff0c\u4f60\u53ef\u80fd\u53ea\u60f3\u5728\u7a0b\u5e8f\u4e2d\u4f7f\u7528\u5230\u5b83\u4eec\u65f6\u624d\u4fdd\u5b58\u3002\n\u4e00\u4e2a WeakValueDictionary \u5b9e\u4f8b\u53ea\u4f1a\u4fdd\u5b58\u90a3\u4e9b\u5728\u5176\u5b83\u5730\u65b9\u8fd8\u5728\u88ab\u4f7f\u7528\u7684\u5b9e\u4f8b\u3002\n\u5426\u5219\u7684\u8bdd\uff0c\u53ea\u8981\u5b9e\u4f8b\u4e0d\u518d\u88ab\u4f7f\u7528\u4e86\uff0c\u5b83\u5c31\u4ece\u5b57\u5178\u4e2d\u88ab\u79fb\u9664\u4e86\u3002\u89c2\u5bdf\u4e0b\u4e0b\u9762\u7684\u6d4b\u8bd5\u7ed3\u679c\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "a = get_spam('foo')\nb = get_spam('bar')\nc = get_spam('foo')\nlist(_spam_cache)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "del a\ndel c\nlist(_spam_cache)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "del b\nlist(_spam_cache)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u5bf9\u4e8e\u5927\u90e8\u5206\u7a0b\u5e8f\u800c\u5df2\uff0c\u8fd9\u91cc\u4ee3\u7801\u5df2\u7ecf\u591f\u7528\u4e86\u3002\u4e0d\u8fc7\u8fd8\u662f\u6709\u4e00\u4e9b\u66f4\u9ad8\u7ea7\u7684\u5b9e\u73b0\u503c\u5f97\u4e86\u89e3\u4e0b\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u9996\u5148\u662f\u8fd9\u91cc\u4f7f\u7528\u5230\u4e86\u4e00\u4e2a\u5168\u5c40\u53d8\u91cf\uff0c\u5e76\u4e14\u5de5\u5382\u51fd\u6570\u8ddf\u7c7b\u653e\u5728\u4e00\u5757\u3002\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u5c06\u7f13\u5b58\u4ee3\u7801\u653e\u5230\u4e00\u4e2a\u5355\u72ec\u7684\u7f13\u5b58\u7ba1\u7406\u5668\u4e2d\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import weakref\n\nclass CachedSpamManager:\n    def __init__(self):\n        self._cache = weakref.WeakValueDictionary()\n\n    def get_spam(self, name):\n        if name not in self._cache:\n            s = Spam(name)\n            self._cache[name] = s\n        else:\n            s = self._cache[name]\n        return s\n\n    def clear(self):\n            self._cache.clear()\n\nclass Spam:\n    manager = CachedSpamManager()\n    def __init__(self, name):\n        self.name = name\n\ndef get_spam(name):\n    return Spam.manager.get_spam(name)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd9\u6837\u7684\u8bdd\u4ee3\u7801\u66f4\u6e05\u6670\uff0c\u5e76\u4e14\u4e5f\u66f4\u7075\u6d3b\uff0c\u6211\u4eec\u53ef\u4ee5\u589e\u52a0\u66f4\u591a\u7684\u7f13\u5b58\u7ba1\u7406\u673a\u5236\uff0c\u53ea\u9700\u8981\u66ff\u4ee3manager\u5373\u53ef\u3002"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u8fd8\u6709\u4e00\u70b9\u5c31\u662f\uff0c\u6211\u4eec\u66b4\u9732\u4e86\u7c7b\u7684\u5b9e\u4f8b\u5316\u7ed9\u7528\u6237\uff0c\u7528\u6237\u5f88\u5bb9\u6613\u53bb\u76f4\u63a5\u5b9e\u4f8b\u5316\u8fd9\u4e2a\u7c7b\uff0c\u800c\u4e0d\u662f\u4f7f\u7528\u5de5\u5382\u65b9\u6cd5\uff0c\u5982\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "a = Spam('foo')\nb = Spam('foo')\na is b"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u6709\u51e0\u79cd\u65b9\u5f0f\u53ef\u4ee5\u9632\u6b62\u7528\u6237\u8fd9\u6837\u505a\uff0c\u7b2c\u4e00\u4e2a\u662f\u5c06\u7c7b\u7684\u540d\u5b57\u4fee\u6539\u4e3a\u4ee5\u4e0b\u5212\u7ebf(_)\u5f00\u5934\uff0c\u63d0\u793a\u7528\u6237\u522b\u76f4\u63a5\u8c03\u7528\u5b83\u3002\n\u7b2c\u4e8c\u79cd\u5c31\u662f\u8ba9\u8fd9\u4e2a\u7c7b\u7684 __init__() \u65b9\u6cd5\u629b\u51fa\u4e00\u4e2a\u5f02\u5e38\uff0c\u8ba9\u5b83\u4e0d\u80fd\u88ab\u521d\u59cb\u5316\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "class Spam:\n    def __init__(self, *args, **kwargs):\n        raise RuntimeError(\"Can't instantiate directly\")\n\n    # Alternate constructor\n    @classmethod\n    def _new(cls, name):\n        self = cls.__new__(cls)\n        self.name = name"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u7136\u540e\u4fee\u6539\u7f13\u5b58\u7ba1\u7406\u5668\u4ee3\u7801\uff0c\u4f7f\u7528 Spam._new() \u6765\u521b\u5efa\u5b9e\u4f8b\uff0c\u800c\u4e0d\u662f\u76f4\u63a5\u8c03\u7528 Spam() \u6784\u9020\u51fd\u6570\uff1a"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# ------------------------\u6700\u540e\u7684\u4fee\u6b63\u65b9\u6848------------------------\nclass CachedSpamManager2:\n    def __init__(self):\n        self._cache = weakref.WeakValueDictionary()\n\n    def get_spam(self, name):\n        if name not in self._cache:\n            temp = Spam3._new(name)  # Modified creation\n            self._cache[name] = temp\n        else:\n            temp = self._cache[name]\n        return temp\n\n    def clear(self):\n            self._cache.clear()\n\nclass Spam3:\n    def __init__(self, *args, **kwargs):\n        raise RuntimeError(\"Can't instantiate directly\")\n\n    # Alternate constructor\n    @classmethod\n    def _new(cls, name):\n        self = cls.__new__(cls)\n        self.name = name\n        return self"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\u6700\u540e\u8fd9\u6837\u7684\u65b9\u6848\u5c31\u5df2\u7ecf\u8db3\u591f\u597d\u4e86\u3002\n\u7f13\u5b58\u548c\u5176\u4ed6\u6784\u9020\u6a21\u5f0f\u8fd8\u53ef\u4ee5\u4f7f\u75289.13\u5c0f\u8282\u4e2d\u7684\u5143\u7c7b\u5b9e\u73b0\u7684\u66f4\u4f18\u96c5\u4e00\u70b9(\u4f7f\u7528\u4e86\u66f4\u9ad8\u7ea7\u7684\u6280\u672f)\u3002"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.7.1"
    },
    "toc": {
      "base_numbering": 1,
      "nav_menu": {},
      "number_sections": true,
      "sideBar": true,
      "skip_h1_title": true,
      "title_cell": "Table of Contents",
      "title_sidebar": "Contents",
      "toc_cell": false,
      "toc_position": {},
      "toc_section_display": true,
      "toc_window_display": true
    }
  },
  "nbformat": 4,
  "nbformat_minor": 2
}